簡體   English   中英

測量關於塊數的cuda執行時間

[英]measure cuda execution time with respect to number of blocks

我寫了我的第一個cuda腳本,並想知道它是如何並行化的。 我有一些變量r0_devf_dev ,長度為(*fnum_dev) * 3數組。 在每個塊上,它們按順序讀取。 再就是r_dev ,我讀,和v_dev ,我想在平行於寫,兩者都是長度的陣列gnum * 3

該程序產生我希望它產生的結果,但復雜性(時間與數據大小的關系)不是我所期望的。

我的期望是,當數組v_dev的大小增加時,執行時間保持不變,因為gnum值小於某個維度中允許的塊數。

現實是不同的。 使用以下代碼,測量時間。 觀察到線性復雜性,我將在順序代碼中執行此操作。

dim3 blockGrid(gnum);

cudaEvent_t start, stop;
float time;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, 0);

// the actual calculation
stokeslets<<<blockGrid, 1>>>(fnum_dev, r0_dev, f_dev, r_dev, v_dev);

// time measurement
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventElapsedTime(&time, start, stop);

題:

如上所述,我的期望是錯的嗎? 還有哪些其他考慮因素很重要?

細節

以下顯示了stokeslet的實現。 也許我在做那些不好的事情?

__device__ void gridPoint(int offset, float* r0, float* f, float* r, float* v) {
    int flatInd = 3 * offset;

    float dr[3];
    float len = 0;
    float drf = 0;

    for (int i = 0; i < 3; i++) {
        dr[i] = r[i] - r0[i + flatInd];
        len += dr[i] * dr[i];
        drf += dr[i] * f[i + flatInd];
    }

    len = sqrt(len);
    float fak = 1 / (8 * 3.1416 * 0.7);
    v[0] +=  (fak / len) * (f[0 + flatInd] + (dr[0]) * drf / (len * len));
    v[1] +=  (fak / len) * (f[1 + flatInd] + (dr[1]) * drf / (len * len));
    v[2] +=  (fak / len) * (f[2 + flatInd] + (dr[2]) * drf / (len * len));
}


__global__ void stokeslets(int* fnum, float* r0, float* f, float* r, float* v) {
    // where are we (which block, which is equivalent to the grid point)?
    int idx = blockIdx.x;

    // we want to add all force contributions
    float rh[3] = {r[3 * idx + 0], r[3 * idx + 1], r[3 * idx + 2]};

    float vh[3] = {0, 0, 0};
    for (int i=0; i < *fnum; i++) {
        gridPoint(i, r0, f, rh, vh);
    }
    // sum intermediate velocity vh
    int flatInd = 3 * idx;
    v[0 + flatInd] += vh[0];
    v[1 + flatInd] += vh[1];
    v[2 + flatInd] += vh[2];
}

代碼的主要問題是您運行的多個塊只包含一個線程

引用CUDA C編程指南

NVIDIA GPU架構圍繞可擴展的多線程流式多處理器(SM)陣列構建。 當主機CPU上的CUDA程序調用內核網格時,將枚舉網格塊並將其分配給具有可用執行容量的多處理器。 線程塊的線程在一個多處理器上並發執行,並且多個線程塊可以在一個多處理器上並發執行。 當線程塊終止時,在空出的多處理器上啟動新塊。

多處理器旨在同時執行數百個線程。

引用答案如何將CUDA塊/變形/線程映射到CUDA核心?

程序員將工作划分為線程,將線程划分為線程塊,將線程塊划分為網格。 計算工作分配器將線程塊分配給流式多處理器(SM)。 一旦將線程塊分配給SM,就會分配線程塊的資源(warp和共享內存),並將線程划分為32個線程的組,稱為warps。 一旦分配了warp,它就被稱為主動warp。 兩個warp調度程序每個周期選擇兩個活動warp並將warp調度到執行單元

從兩個帶有粗體標記的句子開始, 每個流多處理器每個時鍾周期只運行2個線程 這是您觀察與順序情況基本相同的計算復雜性的主要原因。

建議重寫代碼/內核以承載每個塊運行多個線程的可能性。

進一步閱讀: 費米建築白皮書

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM