以下代碼用於測試cudaMemcpyAsync的同步行爲。奇怪的cudaMemcpyAsync同步行爲
#include <iostream>
#include <sys/time.h>
#define N 100000000
using namespace std;
int diff_ms(struct timeval t1, struct timeval t2)
{
return (((t1.tv_sec - t2.tv_sec) * 1000000) +
(t1.tv_usec - t2.tv_usec))/1000;
}
double sumall(double *v, int n)
{
double s=0;
for (int i=0; i<n; i++) s+=v[i];
return s;
}
int main()
{
int i;
cudaStream_t strm;
cudaStreamCreate(&strm);
double *h0;
double *h1;
cudaMallocHost(&h0,N*sizeof(double));
cudaMallocHost(&h1,N*sizeof(double));
for (i=0; i<N; i++) h0[i]=99./N;
double *d;
cudaMalloc(&d,N*sizeof(double));
struct timeval t1, t2; gettimeofday(&t1,NULL);
cudaMemcpyAsync(d,h0,N*sizeof(double),cudaMemcpyHostToDevice,strm);
gettimeofday(&t2, NULL); printf("cuda H->D %d takes: %d ms\n",i, diff_ms(t2, t1)); gettimeofday(&t1, NULL);
cudaMemcpyAsync(h1,d,N*sizeof(double),cudaMemcpyDeviceToHost,strm);
gettimeofday(&t2, NULL); printf("cuda D->H %d takes: %d ms\n",i, diff_ms(t2, t1)); gettimeofday(&t1, NULL);
cout<<"sum h0: "<<sumall(h0,N)<<endl;
cout<<"sum h1: "<<sumall(h1,N)<<endl;
cudaStreamDestroy(strm);
cudaFree(d);
cudaFreeHost(h0);
cudaFreeHost(h1);
return 0;
}
H0/H1的打印提示,cudaMemcpyAsync與主機
sum h0: 99
sum h1: 99
但是同步,時差涵蓋cudaMemcpyAsync呼籲表明,他們不與主機
cuda H->D 100000000 takes: 0 ms
cuda D->H 100000000 takes: 0 ms
同步
因爲這不被cuda-profiling結果支持:
method=[ memcpyHtoDasync ] gputime=[ 154896.734 ] cputime=[ 17.000 ]
method=[ memcpyDtoHasync ] gputime=[ 141175.578 ] cputime=[ 6.000 ]
不知道爲什麼...
感謝您的回答。但根據你的解釋,「總和h1」不應該是99,因爲「h1」從未在主機上初始化過,對吧? –
什麼讓事情更奇怪是,如果我註釋掉{{{cout <<「sum h0:」<< sumall(h0,N)<< endl;}}}行,「sum h1」這一行會打印出一些未定義的結果,這是預期的。 –
您在主機上初始化h0。然後,您將h0複製到設備上的d。然後,您從設備上的d複製到主機上的h1。爲什麼你認爲主機h1在這個序列之後不會匹配主機h0?現在,就註釋中的最後一個問題而言,爲什麼註釋掉該行會產生變化是因爲主機上d的最後一個副本爲h1也是異步的,所以下面的代碼立即開始。在主機上將d複製到h1與sumall之間存在爭用條件。顯然,h0的sumall給了複製h1完成的足夠時間。 –