各位 Cuda 程序员,
我正在尝试使用轮询机制实现 cpu-gpu 回调机制。我有 2 个长度为 1 的数组(a 和 cpuflag,对应于设备端 dev_a 和 gpuflag)(基本上是 2 个变量)。
首先 CPU 清除 a 并等待 gpuflag 的更新。GPU 看到这个 a 的清除,然后更新 gpuflag。CPU 异步不断地将 gpuflag 传输到 cpuflag 并等待标志中的更新。一旦 CPU 看到更新,它会再次重置 a 并将其异步发送到 gpu。GPU 再次看到 a 的清除并更新 gpuflag 并且乒乓过程继续。我希望这个过程持续 100 次。
整个代码在这里。你可以通过说 nvcc -o output filename.cu 来编译它我无法理解为什么代码没有表现出乒乓行为。非常感谢任何形式的帮助。提前致谢。
#include <stdio.h>
#define LEN 1
#define MAX 100
__global__ void myKernel(int len, int *dev_a, int *gpuflag) {
int tid = threadIdx.x;
gpuflag[tid] = 0;
while(true){
//Check if cpu has completed work
if(dev_a[tid] == 0){
//Do gpu work and increment flag
dev_a[tid] = 1;
gpuflag[tid]++;
//Wait till cpu detects the flag increment and resets
while(true){
if(dev_a[tid] == 0){
break;
}
}
}
//Max 100 ping pongs
if(gpuflag[tid]==MAX){
break;
}
}
}
int main( void ) {
int index, *cpuflag, *gpuflag, value;
int *a;
int *dev_a;
cudaStream_t stream0, stream1;
cudaStreamCreate( &stream0 );
cudaStreamCreate( &stream1 );
cudaMalloc ( (void**)&gpuflag, LEN*sizeof(int) );
cudaMemset ( gpuflag, 0, LEN*sizeof(int) );
cudaHostAlloc( (void**)&cpuflag, LEN*sizeof(int), cudaHostAllocDefault );
cudaMalloc ( (void**)&dev_a, LEN*sizeof(int) );
cudaMemset ( dev_a, 0, LEN*sizeof(int) );
cudaHostAlloc( (void**)&a, LEN*sizeof(int), cudaHostAllocDefault );
//Reset everything
for(int i=0; i<LEN; i++)
a[i] = 0;
//Auxillary variables
index = 0;
value = 1;
//call kernel
myKernel<<<1,1,0,stream0>>>(LEN, dev_a, gpuflag);
while(true){
//Asynchronously copy gpu flag
cudaMemcpyAsync(cpuflag, gpuflag, LEN*sizeof(int), cudaMemcpyDeviceToHost, stream1);
//Check if increment has happened or not
if(cpuflag[index] == value){
//if yes, reset
for(int i=0; i<LEN; i++)
a[i] = 0;
//transfer asynchronously
cudaMemcpyAsync(dev_a, a, LEN*sizeof(int), cudaMemcpyHostToDevice, stream1);
//increment pattern
value++;
printf("GPU updated once. Value is a[%d] = %d, cpuflag = %d\n", index, a[index], cpuflag[index]);
} else {
printf("------------GPU didn't updated. Value is a[%d] = %d, cpuflag = %d\n", index, a[index], cpuflag[index]);
}
//Max 100 ping-pongs
if(value == MAX){
break;
}
}
cudaFreeHost(a);
cudaFreeHost(cpuflag);
cudaFree(dev_a);
cudaFree(gpuflag);
cudaStreamDestroy( stream0 );
cudaStreamDestroy( stream1 );
return 0;
}