我在嘗試編寫CUDA程序時遇到困難。我有一個大約524k浮點值(1.0)的數組,我使用縮減技術來添加所有的值。如果我只想運行一次,問題就可以正常工作,但我真的想多次運行內核,以便最終總結超過10億個值。CUDA - 多次調用內核
我以524k爲單位做這件事的原因是當我在GPU上超過100萬時,我總是得到零。這應該不會超過卡上的內存,但在這一點上總是失敗。
無論如何,當我循環內核只有一次,一切工作正常。也就是說,沒有循環是好的。當我用循環運行時,它返回零。我懷疑我會走出一些地方,但我無法弄清楚。這讓我瘋狂。
任何幫助表示讚賞,
感謝,
鋁
下面是代碼:
#include <stdio.h>
#include <stdlib.h>
#include "cutil.h"
#define TILE_WIDTH 512
#define WIDTH 524288
//#define WIDTH 1048576
#define MAX_WIDTH 524288
#define BLOCKS WIDTH/TILE_WIDTH
__global__ void PartSum(float * V_d)
{
int tx = threadIdx.x;
int bx = blockIdx.x;
__shared__ float partialSum[TILE_WIDTH];
for(int i = 0; i < WIDTH/TILE_WIDTH; ++i)
{
partialSum[tx] = V_d[bx * TILE_WIDTH + tx];
__syncthreads();
for(unsigned int stride = 1; stride < blockDim.x; stride *= 2)
{
__syncthreads();
if(tx % (2 * stride) == 0)
partialSum[tx] += partialSum[tx + stride];
}
}
if(tx % TILE_WIDTH == 0)
V_d[bx * TILE_WIDTH + tx] = partialSum[tx];
}
int main(int argc, char * argv[])
{
float * V_d;
float * V_h;
float * R_h;
float * Result;
float * ptr;
dim3 dimBlock(TILE_WIDTH,1,1);
dim3 dimGrid(BLOCKS,1,1);
// Allocate memory on Host
if((V_h = (float *)malloc(sizeof(float) * WIDTH)) == NULL)
{
printf("Error allocating memory on host\n");
exit(-1);
}
if((R_h = (float *)malloc(sizeof(float) * MAX_WIDTH)) == NULL)
{
printf("Error allocating memory on host\n");
exit(-1);
}
// If MAX_WIDTH is not a multiple of WIDTH, this won't work
if(WIDTH % MAX_WIDTH != 0)
{
printf("The width of the vector must be a multiple of the maximum width\n");
exit(-3);
}
// Initialize memory on host with 1.0f
ptr = V_h;
for(long long i = 0; i < WIDTH; ++i)
{
*ptr = 1.0f;
ptr = &ptr[1];
}
ptr = V_h;
// Allocate memory on device in global memory
cudaMalloc((void**) &V_d, MAX_WIDTH*(sizeof(float)));
float Pvalue = 0.0f;
for(int i = 0; i < WIDTH/MAX_WIDTH; ++i)
{
if((Result = (float *) malloc(sizeof(float) * WIDTH)) == NULL)
{
printf("Error allocating memory on host\n");
exit(-4);
}
for(int j = 0; j < MAX_WIDTH; ++j)
{
Result[j] = *ptr;
ptr = &ptr[1];
}
ptr = &V_h[i*MAX_WIDTH];
// Copy portion of data to device
cudaMemcpy(V_d, Result, MAX_WIDTH*(sizeof(float)), cudaMemcpyHostToDevice);
// Execute Kernel
PartSum<<<dimGrid, dimBlock>>>(V_d);
// Copy data back down to host
cudaMemcpy(R_h, V_d, MAX_WIDTH*(sizeof(float)), cudaMemcpyDeviceToHost);
for(int i = 0; i < MAX_WIDTH; i += TILE_WIDTH)
{
Pvalue += R_h[i];
}
printf("Pvalue == %f\n", Pvalue);
free(Result);
}
// printf("WIDTH == %d items\n", WIDTH);
// printf("Value: %f\n", Pvalue);
cudaFree(V_d);
free(V_h);
free(R_h);
return(1);
}
好吧,我想我已經縮小到與問題V_d在設備上。我懷疑我已經超出了陣列的範圍了。如果我分配了實際需要的內存量的2倍,程序將以預期的結果完成。問題是,我無法弄清楚造成問題的原因。
鋁
你有使用cudaMemcpyDeviceToHost的特殊原因嗎?既然你想要更多的內核迭代,你可以考慮使用'cudaMemcpyDeviceToDevice'來代替。 – karlphillip
我不相信你真的需要CUDA - 這將會是I/O的主導因素,因爲你只需要每點添加一個操作 - 你也可以使用CPU。你有沒有對這個實現的CPU實現進行基準測試?你認爲CUDA的實現可能會快多少,因爲它全部是數據移動,幾乎沒有計算? –
這對我來說是一個學習實驗。我意識到這並不高效。 –