摘要
本文深入讲解DolphinDB向量化计算技术。从向量化原理到向量化操作,从批量计算到性能对比,从内存优化到实战应用,全面介绍向量化计算的核心方法。通过丰富的代码示例,帮助读者掌握高性能数据处理的核心技能。
一、向量化计算概述
1.1 什么是向量化计算
向量化计算是对整个向量(数组)进行批量操作:
#mermaid-svg-bxCJaGNYsKtseDkM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bxCJaGNYsKtseDkM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bxCJaGNYsKtseDkM .error-icon{fill:#552222;}#mermaid-svg-bxCJaGNYsKtseDkM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bxCJaGNYsKtseDkM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bxCJaGNYsKtseDkM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bxCJaGNYsKtseDkM .marker.cross{stroke:#333333;}#mermaid-svg-bxCJaGNYsKtseDkM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bxCJaGNYsKtseDkM p{margin:0;}#mermaid-svg-bxCJaGNYsKtseDkM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bxCJaGNYsKtseDkM .cluster-label text{fill:#333;}#mermaid-svg-bxCJaGNYsKtseDkM .cluster-label span{color:#333;}#mermaid-svg-bxCJaGNYsKtseDkM .cluster-label span p{background-color:transparent;}#mermaid-svg-bxCJaGNYsKtseDkM .label text,#mermaid-svg-bxCJaGNYsKtseDkM span{fill:#333;color:#333;}#mermaid-svg-bxCJaGNYsKtseDkM .node rect,#mermaid-svg-bxCJaGNYsKtseDkM .node circle,#mermaid-svg-bxCJaGNYsKtseDkM .node ellipse,#mermaid-svg-bxCJaGNYsKtseDkM .node polygon,#mermaid-svg-bxCJaGNYsKtseDkM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bxCJaGNYsKtseDkM .rough-node .label text,#mermaid-svg-bxCJaGNYsKtseDkM .node .label text,#mermaid-svg-bxCJaGNYsKtseDkM .image-shape .label,#mermaid-svg-bxCJaGNYsKtseDkM .icon-shape .label{text-anchor:middle;}#mermaid-svg-bxCJaGNYsKtseDkM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bxCJaGNYsKtseDkM .rough-node .label,#mermaid-svg-bxCJaGNYsKtseDkM .node .label,#mermaid-svg-bxCJaGNYsKtseDkM .image-shape .label,#mermaid-svg-bxCJaGNYsKtseDkM .icon-shape .label{text-align:center;}#mermaid-svg-bxCJaGNYsKtseDkM .node.clickable{cursor:pointer;}#mermaid-svg-bxCJaGNYsKtseDkM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bxCJaGNYsKtseDkM .arrowheadPath{fill:#333333;}#mermaid-svg-bxCJaGNYsKtseDkM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bxCJaGNYsKtseDkM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bxCJaGNYsKtseDkM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bxCJaGNYsKtseDkM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bxCJaGNYsKtseDkM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bxCJaGNYsKtseDkM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bxCJaGNYsKtseDkM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bxCJaGNYsKtseDkM .cluster text{fill:#333;}#mermaid-svg-bxCJaGNYsKtseDkM .cluster span{color:#333;}#mermaid-svg-bxCJaGNYsKtseDkM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bxCJaGNYsKtseDkM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bxCJaGNYsKtseDkM rect.text{fill:none;stroke-width:0;}#mermaid-svg-bxCJaGNYsKtseDkM .icon-shape,#mermaid-svg-bxCJaGNYsKtseDkM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bxCJaGNYsKtseDkM .icon-shape p,#mermaid-svg-bxCJaGNYsKtseDkM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bxCJaGNYsKtseDkM .icon-shape .label rect,#mermaid-svg-bxCJaGNYsKtseDkM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bxCJaGNYsKtseDkM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bxCJaGNYsKtseDkM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bxCJaGNYsKtseDkM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 向量化计算
标量计算
逐元素循环
向量化计算
批量操作
优势
减少循环
SIMD加速
内存连续
1.2 向量化 vs 标量化
| 特性 | 标量化 | 向量化 |
|---|---|---|
| 操作方式 | 逐元素循环 | 批量操作 |
| 性能 | 较慢 | 快10-100倍 |
| 代码 | 复杂 | 简洁 |
| 内存 | 分散 | 连续 |
1.3 DolphinDB向量化优势
| 优势 | 说明 |
|---|---|
| 原生支持 | 内置向量化 |
| SIMD加速 | CPU指令优化 |
| 内存优化 | 连续内存访问 |
| 简洁语法 | 向量化表达式 |
二、向量化操作
2.1 基本运算
python
// 创建向量
a = 1..10
b = 11..20
// 向量化加法
a + b // [12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
// 向量化减法
b - a // [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
// 向量化乘法
a * b // [11, 24, 39, 56, 75, 96, 119, 144, 171, 200]
// 向量化除法
b \ a // [11, 6, 5.33, 4.25, 3.8, 3.33, 3, 2.75, 2.56, 2.4]
2.2 数学函数
python
// 向量化数学函数
x = 1..10
// 三角函数
sin(x)
cos(x)
tan(x)
// 指数对数
exp(x)
log(x)
log10(x)
// 幂运算
pow(x, 2)
sqrt(x)
// 取整
floor(x)
ceil(x)
round(x)
2.3 统计函数
python
// 向量化统计函数
data = rand(20.0..30.0, 1000)
// 基本统计
sum(data) // 总和
avg(data) // 平均值
max(data) // 最大值
min(data) // 最小值
std(data) // 标准差
var(data) // 方差
med(data) // 中位数
mode(data) // 众数
2.4 条件运算
python
// 向量化条件运算
data = 1..10
// 条件赋值
iif(data > 5, "大", "小")
// ["小", "小", "小", "小", "小", "大", "大", "大", "大", "大"]
// 多条件
iif(data < 3, "小",
iif(data < 7, "中", "大"))
// ["小", "小", "中", "中", "中", "中", "大", "大", "大", "大"]
三、向量化 vs 循环
3.1 性能对比
python
// ========== 性能对比测试 ==========
// 标量化:循环计算
def scalarSum(data) {
total = 0.0
for (v in data) {
total += v
}
return total
}
// 向量化:直接计算
def vectorSum(data) {
return sum(data)
}
// 测试数据
data = rand(1000.0, 1000000)
// 性能测试
timer scalarSum(data) // 循环版本
timer vectorSum(data) // 向量化版本
// 结果:向量化快10-100倍
3.2 代码对比
python
// 标量化:复杂代码
def scalarAdd(a, b) {
result = array(DOUBLE, a.size())
for (i in 0..a.size()) {
result[i] = a[i] + b[i]
}
return result
}
// 向量化:简洁代码
def vectorAdd(a, b) {
return a + b
}
// 测试
a = rand(1000.0, 100000)
b = rand(1000.0, 100000)
timer scalarAdd(a, b)
timer vectorAdd(a, b)
四、向量化技巧
4.1 避免显式循环
python
// 不推荐:显式循环
def slowProcess(data) {
result = array(DOUBLE, data.size())
for (i in 0..data.size()) {
result[i] = data[i] * 2 + 1
}
return result
}
// 推荐:向量化
def fastProcess(data) {
return data * 2 + 1
}
4.2 使用内置函数
python
// 不推荐:自己实现
def mySum(data) {
total = 0.0
for (v in data) {
total += v
}
return total
}
// 推荐:使用内置函数
sum(data)
4.3 批量操作
python
// 批量操作:一次处理多列
t = table(
rand(20.0..30.0, 1000) as temp1,
rand(20.0..30.0, 1000) as temp2,
rand(20.0..30.0, 1000) as temp3
)
// 向量化:多列同时计算
select temp1, temp2, temp3,
(temp1 + temp2 + temp3) / 3 as avg_temp,
max(temp1, temp2, temp3) as max_temp,
min(temp1, temp2, temp3) as min_temp
from t
五、内存优化
5.1 内存连续性
python
// 内存连续:向量化操作更高效
// DolphinDB向量存储在连续内存中
// 创建大向量
largeVector = rand(1000.0, 10000000)
// 向量化操作:内存连续访问
timer sum(largeVector) // 快
// 避免频繁创建小向量
5.2 避免内存拷贝
python
// 避免不必要的拷贝
data = rand(1000.0, 1000000)
// 不推荐:创建多个中间结果
step1 = data * 2
step2 = step1 + 1
step3 = sqrt(step2)
// 推荐:链式操作
result = sqrt(data * 2 + 1)
5.3 数据类型优化
python
// 选择合适的数据类型
// INT vs DOUBLE
// 整数计算更快
intData = 1..1000000
timer sum(intData)
// 浮点计算稍慢
floatData = double(1..1000000)
timer sum(floatData)
六、实战案例
6.1 数据标准化
python
// ========== 向量化数据标准化 ==========
// 创建数据
t = table(
1..10000 as id,
rand(20.0..30.0, 10000) as temperature,
rand(40.0..60.0, 10000) as humidity
)
// 向量化标准化
select id, temperature, humidity,
(temperature - avg(temperature)) / std(temperature) as temp_normalized,
(humidity - avg(humidity)) / std(humidity) as humid_normalized
from t
// 或者使用函数
def normalize(data) {
return (data - avg(data)) / std(data)
}
select id,
normalize(temperature) as temp_norm,
normalize(humidity) as humid_norm
from t
6.2 批量特征计算
python
// ========== 向量化特征计算 ==========
// 创建时间序列数据
t = table(
2024.01.01T00:00:00 + 0..99999 * 60000 as timestamp,
rand(20.0..30.0, 100000) as temperature,
rand(40.0..60.0, 100000) as humidity
)
// 向量化特征计算
select timestamp, temperature, humidity,
// 滑动特征
mavg(temperature, 10) as temp_ma10,
mstd(temperature, 10) as temp_std10,
mmax(temperature, 10) as temp_max10,
mmin(temperature, 10) as temp_min10,
// 差分特征
temperature - prev(temperature) as temp_diff,
// 比率特征
temperature / humidity as temp_humid_ratio
from t
6.3 批量异常检测
python
// ========== 向量化异常检测 ==========
// 创建数据
t = table(
1..10000 as id,
rand(20.0..30.0, 10000) as temperature
)
// 向量化异常检测
select id, temperature,
// Z-Score异常检测
abs(temperature - avg(temperature)) / std(temperature) as zscore,
abs(temperature - avg(temperature)) > 3 * std(temperature) as is_anomaly,
// IQR异常检测
percentile(temperature, 25) as q1,
percentile(temperature, 75) as q3,
temperature < percentile(temperature, 25) - 1.5 * (percentile(temperature, 75) - percentile(temperature, 25)) or
temperature > percentile(temperature, 75) + 1.5 * (percentile(temperature, 75) - percentile(temperature, 25)) as is_iqr_anomaly
from t
七、性能基准
7.1 基准测试
python
// ========== 性能基准测试 ==========
// 测试数据
data = rand(1000.0, 10000000)
// 测试1:求和
timer sum(data)
// 测试2:平均值
timer avg(data)
// 测试3:标准差
timer std(data)
// 测试4:排序
timer sort(data)
// 测试5:向量化运算
timer data * 2 + 1
7.2 性能对比表
| 操作 | 标量化(ms) | 向量化(ms) | 加速比 |
|---|---|---|---|
| 求和 | 100 | 5 | 20x |
| 平均值 | 120 | 6 | 20x |
| 标准差 | 200 | 10 | 20x |
| 加法 | 150 | 3 | 50x |
| 乘法 | 150 | 3 | 50x |
八、总结
本文详细介绍了DolphinDB向量化计算:
- 向量化原理:批量操作、SIMD加速
- 向量化操作:基本运算、数学函数、统计函数
- 性能对比:向量化 vs 标量化
- 向量化技巧:避免循环、使用内置函数
- 内存优化:内存连续、避免拷贝
- 实战应用:数据标准化、特征计算、异常检测
思考题:
- 向量化为什么比标量化快?
- 如何选择向量化操作?
- 如何优化向量化性能?