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

时间:2016-06-07 17:08:45

标签: c++ cuda shared-memory

我有以下CUDA内核:

Int

TL; DR 我想找到一种方法将__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); } } 存储在共享(data)内存中。我不明白的是如何使用多个线程填充共享变量。

我见过像this one这样的例子,其中__shared__被线程复制到共享内存线程(例如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()

Unflattened,数据是固定大小的2D数组,类似于:

data[0]
data[1]
data[2]
...

至于内核调用,我迭代数据项并为n个数据行(约350万)调用n次:

[87.6, 85.4, 88.2, 86.1]
 84.1, 86.5, 86.7, 85.9
 86.7, 86.5, 86.2, 86.1
 ...]

2 个答案:

答案 0 :(得分:1)

正如您的评论中所确认的那样,您希望在每个3.5米数据上应用20k(此数字来自您之前的问题)策略并检查20k x 3.5m的结果。

如果没有共享内存,您必须从全局内存中读取所有数据20k次或所有策略3.5m次。

共享内存可以通过减少全局内存访问来加速您的程序。假设您每次都可以读取1k策略和1k数据到共享内存,检查1k x 1k结果,然后重复此操作直到所有内容都被清除。通过这种方式,您可以将全局mem访问权限减少到所有数据的20倍和所有策略的3.5k倍。这种情况类似于vector-vectoer交叉产品。您可以找到一些参考代码以获取更多细节。

但是你的每个数据都很大(838-D矢量),也许策略也很大。您可能无法在共享内存中缓存大量内容(每个块只有~48k,具体取决于设备类型)。因此情况变为矩阵 - 矩阵乘法。为此,您可以从矩阵乘法代码中获得一些提示,如以下链接所示。

http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared-memory

答案 1 :(得分:1)

对于将来寻找类似答案的人来说,这就是我最终为我的内核功能所做的:

__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。我不知道应该怎么做,但那对我有用。