我有一个向量vector<vector<double>> data
的向量。我只想复制"2D矩阵"中包含的信息,因为CUDA中没有矢量。所以我使用的第一种方法是
vector<vector<double>> *values;
vector<vector<double>>::iterator it;
double *d_values;
double *dst;
checkCudaErr(
cudaMalloc((void**)&d_values, sizeof(double)*M*N)
);
dst = d_values;
for (it = values->begin(); it != values->end(); ++it){
double *src = &((*it)[0]);
size_t s = it->size();
checkCudaErr(
cudaMemcpy(dst, src, sizeof(double)*s, cudaMemcpyHostToDevice)
);
dst += s;
}
在使用NVVP进行评测后,我得到了非常低的cudaMempcpy吞吐量。我认为这是合乎逻辑的,因为我只发送了少量每个cudaMemcpy调用中的字节。所以我决定稍微修改一下代码,试图改进这一点,所以第二种方法是
double *h_values = new double[M*N];
dst = h_values;
for (it = values->begin(); it != values->end(); ++it){
double *src = &((*it)[0]);
size_t s = it->size();
memcpy(dst, src, sizeof(double)*s);
dst += s;
}
checkCudaErr(
cudaMemcpy(d_values, h_values, sizeof(double)*M*N, cudaMemcpyHostToDevice)
);
分析后的结果仍然是低memcpy吞吐量。所以,我的问题是,如何改进从主机到设备的拷贝?
我用的是Quadro K4000。第一种情况下我得到了25 MB/s,第二种情况下大约得到了2 GB/s。M=5和N=2000000。我必须说,M的值是一个常见的值,但有时它可以达到50。
吞吐量缓慢的一个原因可能是您将双矩阵分配为new。此内存未被页面锁定。您可以使用系统函数(不知道您使用的是哪种系统),也可以使用提供此功能的cuda函数。它将是cudaMallocHost
。
只需删除您的=new double[M*N]
,并将h_values
设置为cudaMallocHost(&h_values, sizeof(double)*M*N)
(当然不要删除它,而是释放它(使用cudaFreeHost
))。
Btw。理论上的最高速度是8 GB/s(PCI 2.0 x 16通道),实际上您将保持在它以下(大约6 GB/s)。