簡體   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