繁体   English   中英

如何在CUDA内核中使用共享内存?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM