簡體   English   中英

盡管CudaSuccess,CUDA cudaMemCpy似乎沒有復制

[英]CUDA cudaMemCpy doesn't appear to copy despite CudaSuccess

我剛開始使用CUDA,這是我的第一個項目。 我已經搜索了這個問題,雖然我注意到其他人也有類似的問題,但是這些建議似乎都與我的特定問題無關,也沒有對我的情況有所幫助。

作為練習,我試圖使用CUDA編寫n體模擬。 在此階段,我對我的特定實現是否高效不感興趣,我只是在尋找可行的方法,以后可以對其進行改進。 一旦工作,我還需要稍后更新代碼,以使用我的SLI配置。

這是該過程的簡要概述:

  1. 創建X和Y位置,速度,加速度矢量。
  2. 在GPU上創建相同的向量並跨向量復制值
  3. 在一個循環中:(i)計算迭代的加速度,(ii)將加速度應用於速度和位置,並且(iii)將位置復制回主機以供顯示。

(顯示尚未實現。我將在以后進行)

現在不用擔心加速度計算功能,這是更新功能:

__global__ void apply_acc(double* pos_x, double* pos_y, double* vel_x, double* vel_y, double* acc_x, double* acc_y, int N)
{
    int i = threadIdx.x;

    if (i < N);
    {
        vel_x[i] += acc_x[i];
        vel_y[i] += acc_y[i];

        pos_x[i] += vel_x[i];
        pos_y[i] += vel_y[i];
    }
}

這是main方法中的一些代碼:

cudaError t;

t = cudaMalloc(&d_pos_x, N * sizeof(double));
t = cudaMalloc(&d_pos_y, N * sizeof(double));
t = cudaMalloc(&d_vel_x, N * sizeof(double));
t = cudaMalloc(&d_vel_y, N * sizeof(double));
t = cudaMalloc(&d_acc_x, N * sizeof(double));
t = cudaMalloc(&d_acc_y, N * sizeof(double));

t = cudaMemcpy(d_pos_x, pos_x, N * sizeof(double), cudaMemcpyHostToDevice);
t = cudaMemcpy(d_pos_y, pos_y, N * sizeof(double), cudaMemcpyHostToDevice);
t = cudaMemcpy(d_vel_x, vel_x, N * sizeof(double), cudaMemcpyHostToDevice);
t = cudaMemcpy(d_vel_y, vel_y, N * sizeof(double), cudaMemcpyHostToDevice);
t = cudaMemcpy(d_acc_x, acc_x, N * sizeof(double), cudaMemcpyHostToDevice);
t = cudaMemcpy(d_acc_y, acc_y, N * sizeof(double), cudaMemcpyHostToDevice);

while (true)
{
    calc_acc<<<1, N>>>(d_pos_x, d_pos_y, d_vel_x, d_vel_y, d_acc_x, d_acc_y, N);
    apply_acc<<<1, N>>>(d_pos_x, d_pos_y, d_vel_x, d_vel_y, d_acc_x, d_acc_y, N);

    t = cudaMemcpy(pos_x, d_pos_x, N * sizeof(double), cudaMemcpyDeviceToHost);
    t = cudaMemcpy(pos_y, d_pos_y, N * sizeof(double), cudaMemcpyDeviceToHost);

    std::cout << pos_x[0] << std::endl;
}

在每個循環中, cout寫入相同的值,無論原始創建位置數組時將其設置為什么隨機值。 如果我將apply_acc的代碼apply_acc為類似以下內容:

__global__ void apply_acc(double* pos_x, double* pos_y, double* vel_x, double* vel_y, double* acc_x, double* acc_y, int N)
{
    int i = threadIdx.x;

    if (i < N);
    {
        pos_x[i] += 1.0;
        pos_y[i] += 1.0;
    }
}

那么它仍然會提供相同的值,因此不會調用apply_acccudaMemcpy不會將數據復制回去。

所有的cudaMalloccudaMemcpy調用都返回cudaScuccess

這里是完整代碼的PasteBin鏈接。 遵循起來應該很簡單,因為各種數組都有很多重復。

就像我說的那樣,我以前從未編寫過CUDA代碼,而是根據NVidia的#2 CUDA示例視頻編寫的,該人員編寫了並行數組附加代碼。 我不確定是否會有所不同,但是我將2x GTX970與最新的NVidia驅動程序和CUDA 7.0 RC一起使用,並且我選擇在安裝CUDA時不安裝捆綁的驅動程序,因為它們比我的要舊。

這行不通:

const int N = 100000;
...
calc_acc<<<1, N>>>(...);
apply_acc<<<1, N>>>(...);

內核啟動配置( <<<...>>> )的第二個參數是每個塊的線程參數。 根據您的編譯方式,它限制為512或1024。 這些內核將不會啟動,並且需要通過使用正確的CUDA錯誤檢查來捕獲由此產生的錯誤類型。 僅查看后續CUDA API函數的返回值將不會表明存在這種類型的錯誤(這就是為什么您隨后看到cudaSuccess原因)。

關於概念本身,我建議您進一步了解CUDA線程和塊層次結構 要啟動大量線程,您需要使用內核啟動配置的兩個參數(即前兩個參數中的一個都不為1)。 通常從性能角度來看也是建議的。

暫無
暫無

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

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