2014-03-07 75 views
0

我有一个数组的大小为3000的数组包含0和1.我想要找到第一个数组的位置,有1存储在该位置从第0个索引开始.i将此数组传递给主机和此数组是在设备上计算出来的,然后我顺序计算了Host.in上的索引,我的程序中我希望重复计算4000次或更多次。我想减少这个过程所花费的时间。有没有其他方式可以做到这一点?而且这个阵列实际上是在GPU上计算的,所以我必须每次都传输它。如何减少CudaMemcpy开销

int main() 
{ 
for(int i=0;i<4000;i++) 
{ 
    cudaMemcpy(A,dev_A,sizeof(int)*3000,cudaMemcpyDeviceToHost); 
    int k; 
    for(k=0;k<3000;k++) 
    { 
     if(A[k]==1) 
     { 
      break; 
     } 
    } 
    printf("got k is %d",k); 
} 
} 

完整代码是这样 的#include “cuda.h” 的#include 的#define SIZE 2688 的#define BLOCKS 14 的#define THREADS 192

__global__ void kernel(int *A,int *d_pos) 
{ 
int thread_id=threadIdx.x+blockIdx.x*blockDim.x; 
while(thread_id<SIZE) 
{ 
    if(A[thread_id]==INT_MIN) 
    { 
     *d_pos=thread_id; 
     return; 
    } 
    thread_id+=1; 
} 

}

__global__ void kernel1(int *A,int *d_pos) 
{ 
int thread_id=threadIdx.x+blockIdx.x*blockDim.x; 
if(A[thread_id]==INT_MIN) 
{ 
    atomicMin(d_pos,thread_id); 
} 

}

int main() 
{ 
int pos=INT_MAX,i; 
int *d_pos; 
int A[SIZE]; 
int *d_A; 
for(i=0;i<SIZE;i++) 
{ 
    A[i]=78; 
} 
A[SIZE-1]=INT_MIN; 
cudaMalloc((void**)&d_pos,sizeof(int)); 
cudaMemcpy(d_pos,&pos,sizeof(int),cudaMemcpyHostToDevice); 
cudaMalloc((void**)&d_A,sizeof(int)*SIZE); 
cudaMemcpy(d_A,A,sizeof(int)*SIZE,cudaMemcpyHostToDevice); 

cudaEvent_t start_cp1,stop_cp1; 
    cudaEventCreate(&stop_cp1); 
    cudaEventCreate(&start_cp1); 
    cudaEventRecord(start_cp1,0); 

kernel1<<<BLOCKS,THREADS>>>(d_A,d_pos); 

cudaEventRecord(stop_cp1,0); 
    cudaEventSynchronize(stop_cp1); 
    float elapsedTime_cp1; 
    cudaEventElapsedTime(&elapsedTime_cp1,start_cp1,stop_cp1); 
    cudaEventDestroy(start_cp1); 
    cudaEventDestroy(stop_cp1); 
    printf("\nTime taken by kernel is %f\n",elapsedTime_cp1); 
cudaDeviceSynchronize(); 

cudaEvent_t start_cp,stop_cp; 
    cudaEventCreate(&stop_cp); 
    cudaEventCreate(&start_cp); 
    cudaEventRecord(start_cp,0); 

cudaMemcpy(A,d_A,sizeof(int)*SIZE,cudaMemcpyDeviceToHost); 

    cudaEventRecord(stop_cp,0); 
    cudaEventSynchronize(stop_cp); 
    float elapsedTime_cp; 
    cudaEventElapsedTime(&elapsedTime_cp,start_cp,stop_cp); 
    cudaEventDestroy(start_cp); 
    cudaEventDestroy(stop_cp); 
    printf("\ntime taken by copy of an array is %f\n",elapsedTime_cp); 






    cudaEvent_t start_cp2,stop_cp2; 
    cudaEventCreate(&stop_cp2); 
    cudaEventCreate(&start_cp2); 
    cudaEventRecord(start_cp2,0); 

    cudaMemcpy(&pos,d_pos,sizeof(int),cudaMemcpyDeviceToHost); 

    cudaEventRecord(stop_cp2,0); 
    cudaEventSynchronize(stop_cp2); 
    float elapsedTime_cp2; 
    cudaEventElapsedTime(&elapsedTime_cp2,start_cp2,stop_cp2); 
    cudaEventDestroy(start_cp2); 
    cudaEventDestroy(stop_cp2); 
    printf("\ntime taken by copy of a variable is %f\n",elapsedTime_cp2); 


cudaMemcpy(&pos,d_pos,sizeof(int),cudaMemcpyDeviceToHost); 
printf("\nminimum index is %d\n",pos); 
return 0; 
} 

我该如何减少此代码与其他任何性能选项所花费的总时间。

+0

什么是产生内容的内核速度设备阵列相对于复制操作?它是更快还是更慢? – talonmies

+0

目前形式的代码并不合理。因此,我假设*在循环中调用'cudaMemcpy'之前,启动内核(每次都用新数据填充'dev_A') - 这是正确的吗? – Marco13

+1

是否可以交替更新的设备阵列? – hubs

回答

1

如果您在GPU上运行内核4000次,可能需要通过不同的流在内核上执行异步执行。使用cudaMemCpyAsync对于主机来说可能更快(在执行M倍内核的情况下)。

简要介绍了流和异步执行: https://devblogs.nvidia.com/parallelforall/how-overlap-data-transfers-cuda-cc/

流和并发: http://on-demand.gputechconf.com/gtc-express/2011/presentations/StreamsAndConcurrencyWebinar.pdf

希望这可以帮助...

+0

因此,我的问题是,是否有可能将内核写入的设备阵列交替使用。如果这是不可能的,也许通过某种迭代依赖关系,你的答案不会成为一种选择。如果可能的话,这当然是一个好方法。 – hubs

+0

为什么单变量传输时间和数组大小3000传输时间大致相同? – user3279286