在回测的时候,需要计算很多的指标,对一个时间系列值进行滚动窗口求sum、mean、std......是非常常见的操作,如何提高他们的计算速度呢?
下面以滚动窗口取40,这些窗口里的系列值再求和,为案例进行。
主要目的,用于计算时间的对比
【计算任务】
1、数组有1亿3千万个元素
2、rolling windows = 40
3、function = sum
【结论】
1、CPU多线程后,提速10倍,
2、用GPU计算,比CPU多线程加速10倍
本机配置:AMD 3700X + RTX 2060
一、用CPU计算
(1)单线程计算
using BenchmarkTools
N = 2^27
ary =Array(1:N)
res =similar(ary)
function cpu_fn(ary,res)
for index in ary
size = 40
if index < size
res[index] = 0 #看业务需求,也可以:有多少就算多少
else
for i in index - size + 1 : index
res[index] += ary[i]
end
end
end
return nothing
end
@btime cpu_fn(ary,res) # 4.699s
耗时:4.699s
(2)多线程计算
function cpu_fn_threads(ary,res)
Threads.@threads for index in ary
size = 40
if index < size
res[index] = 0
else
for i in index - size + 1 : index
res[index] += ary[i]
end
end
end
return nothing
end
@btime cpu_fn_threads(ary,res) #439.207ms
耗时:439.207ms (接近半秒)
二、用GPU进行计算
using CUDA
using Test
using BenchmarkTools
function gpu_fn!(ary,res)
index = (blockIdx().x - 1) * blockDim().x + threadIdx().x
size = 40
if index < size
res[index] = 0.0
else
for i in index - size + 1 : index
res[index] += ary[i]
end
end
return nothing
end
N = 2^27
ary = CUDA.CuArray(1:N) # a vector stored on the GPU filled with 1.0 (Float32)
res = CUDA.CuArray(1:N) # a vector stored on the GPU filled with 2.0
numblocks = ceil(Int, N/256)
@cuda threads=256 blocks=numblocks gpu_fn!(ary,res)
#测试计算时间
@btime CUDA.@sync begin # 43.219ms
@cuda threads=256 blocks=numblocks gpu_fn!(ary,res)
end
耗时:43.219ms
三、总结和注意事项
(1)本机的 CPU是 amd 3700x GPU是 rtx2060
(2)单线程耗时4.6秒,多线程耗时439.2ms,然而,如果用GPU计算,耗时为43.2ms
GPU计算时间是CPU多线程的十分之一,是单线程CPU的百分之一,关键是,利用GPU计算后,你可以把CPU解放出来,做别的事情
(3)同步GPU计算的时候用
#关键点 是 【begin】 和 【end】,省去begin和end的话,会出错
CUDA.@sync begin
@cuda threads=256 blocks=numblocks gpu_fn!(ary,res)
end
网友评论