[英]How can I use shared memory here in my CUDA kernel?
我有以下CUDA内核:
__global__ void optimizer_backtest(double *data, Strategy *strategies, int strategyCount, double investment, double profitability) {
// Use a grid-stride loop.
// Reference: https://devblogs.nvidia.com/parallelforall/cuda-pro-tip-write-flexible-kernels-grid-stride-loops/
for (int i = blockIdx.x * blockDim.x + threadIdx.x;
i < strategyCount;
i += blockDim.x * gridDim.x)
{
strategies[i].backtest(data, investment, profitability);
}
}
TL; DR我想找到一种在共享( __shared__
)内存中存储data
的方法。 我不明白的是如何使用多个线程来填充共享变量。
我曾见过这样的例子这样一个地方data
被线程复制到共享内存的线程(如myblock[tid] = data[tid]
但我不知道如何在我的情况下做到这一点。 问题在于,每个线程都需要通过数据集的每次迭代访问整个“行”(平整的)数据(请参见下文中调用内核的更多信息)。
我希望这样的事情:
__global__ void optimizer_backtest(double *data, Strategy *strategies, int strategyCount, int propertyCount, double investment, double profitability) {
__shared__ double sharedData[propertyCount];
// Use a grid-stride loop.
// Reference: https://devblogs.nvidia.com/parallelforall/cuda-pro-tip-write-flexible-kernels-grid-stride-loops/
for (int i = blockIdx.x * blockDim.x + threadIdx.x;
i < strategyCount;
i += blockDim.x * gridDim.x)
{
strategies[i].backtest(sharedData, investment, profitability);
}
}
以下是更多详细信息(如果需要更多信息,请询问!):
strategies
是一个指向列表Strategy
对象,并且data
是指向所分配的扁平数据数组。
在backtest()
我这样访问数据:
data[0]
data[1]
data[2]
...
未展平的数据是固定大小的2D数组,类似于此:
[87.6, 85.4, 88.2, 86.1]
84.1, 86.5, 86.7, 85.9
86.7, 86.5, 86.2, 86.1
...]
至于内核调用,我遍历数据项并为n个数据行(约350万)调用n次:
int dataCount = 3500000;
int propertyCount = 4;
for (i=0; i<dataCount; i++) {
unsigned int dataPointerOffset = i * propertyCount;
// Notice pointer arithmetic.
optimizer_backtest<<<32, 1024>>>(devData + dataPointerOffset, devStrategies, strategyCount, investment, profitability);
}
正如您的评论中确认的那样,您想对3.5m数据中的每一个应用20k(此数字来自您先前的问题)并检查20k x 3.5m的结果。
如果没有共享内存,则必须从全局内存读取20k次所有数据或3.5m次所有策略。
共享内存可以通过减少全局内存访问来加速程序。 假设您每次可以读取1k策略和1k数据以共享mem,检查1k x 1k的结果,然后重复进行直到所有内容都经过检查。 这样,您可以将全局内存访问减少到所有数据的20倍和所有策略的3.5k倍。 这种情况类似于矢量-矢量叉积。 您可以找到一些参考代码以获取更多详细信息。
但是,您的每个数据都很大(838-D矢量),也许策略也很大。 您可能无法在共享内存中缓存很多缓存(根据设备类型,每个块只能缓存约48k)。 因此情况变成了矩阵矩阵乘法之类的东西。 为此,您可以从矩阵乘法代码中获得一些提示,如以下链接所示。
http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory
对于以后寻求类似答案的人们,这是我最终为我的内核函数准备的:
__global__ void optimizer_backtest(double *data, Strategy *strategies, int strategyCount, double investment, double profitability) {
__shared__ double sharedData[838];
if (threadIdx.x < 838) {
sharedData[threadIdx.x] = data[threadIdx.x];
}
__syncthreads();
// Use a grid-stride loop.
// Reference: https://devblogs.nvidia.com/parallelforall/cuda-pro-tip-write-flexible-kernels-grid-stride-loops/
for (int i = blockIdx.x * blockDim.x + threadIdx.x;
i < strategyCount;
i += blockDim.x * gridDim.x)
{
strategies[i].backtest(sharedData, investment, profitability);
}
}
请注意,我在应用程序中同时使用了.cuh和.cu文件,并将其放在.cu文件中。 另请注意,编译目标文件时,我在Makefile中使用--device-c
。 我不知道这是应该怎么做,但这对我有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.