Cuda 主机到设备的低内存拷贝吞吐量

Cuda 主机到设备的低内存拷贝吞吐量,cuda,gpgpu,Cuda,Gpgpu,我有一个向量数据向量。 我只想复制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)

我有一个向量数据向量。 我只想复制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;
}
分析后的结果仍然是低memcpy吞吐量。 所以,我的问题是,如何改进从主机到设备的拷贝


我用的是Quadro K4000。第一个案例的速度是25MB/s,第二个案例的速度是2GB/s。M=5,N=2000000。我必须说M的值是一个普通值,但有时它可以达到50。

吞吐量缓慢的一个原因可能是您使用新值分配双矩阵。此内存没有页面锁定。您可以使用不知道使用哪个系统的系统功能,也可以使用提供此功能的cuda功能。那将是库达马洛霍斯特

只需删除你的=new double[M*N]并使用cudamalochost&h_值、sizeofdouble*M*N设置你的h_值,当然不要删除它,而是使用cudaFreeHost释放它


顺便说一句,理论上的最高速度是8 GB/s PCI 2.0 x 16车道,实际情况下,您将保持在6 GB/s左右。吞吐量缓慢的原因可能是您为双矩阵分配了新的带宽。此内存没有页面锁定。您可以使用不知道使用哪个系统的系统功能,也可以使用提供此功能的cuda功能。那将是库达马洛霍斯特

只需删除你的=new double[M*N]并使用cudamalochost&h_值、sizeofdouble*M*N设置你的h_值,当然不要删除它,而是使用cudaFreeHost释放它


顺便说一句,理论上的最高速度是8 GB/s PCI 2.0 x 16通道,实际情况下,您将保持在6 GB/s左右。您应该更准确一些-我想您不是说memcpy吞吐量低,而是说cudaMemcpy吞吐量低,对吗?为了帮助您,您还应该说明您拥有哪个GPU,实际吞吐量是多少,以及M和N的大小。对不起,是的,我的意思是cudaMemcpy,我只是复制nvvp探查器所说的内容。我刚刚编辑了这个问题。M和N如何映射到原始向量?这是否意味着要复制2000000个向量,每个向量包含5-50个条目,或者反过来复制。您声明第二种情况是在80Mb传输上每秒传输2Gb。这与CUDA附带的标准HostToDevice带宽测试的性能相比如何?M行,N列。是的,Nvidia的visual profiler报告第二种情况的平均速度为2GB/s,我是否应该使用nvprof?。对于可分页内存传输测试,我得到了大约3.7GB/s,所以我可以说我得到了大约50%的可用带宽。如果你使用cudaEvents在这个特定的cudaMemcpy调用上运行自己的带宽测量,你会得到什么样的传输速率?你应该更准确-我想你不是说你的memcpy吞吐量低,但是你的cudaMemcpy吞吐量很低,对吗?为了帮助您,您还应该说明您拥有哪个GPU,实际吞吐量是多少,以及M和N的大小。对不起,是的,我的意思是cudaMemcpy,我只是复制nvvp探查器所说的内容。我刚刚编辑了这个问题。M和N如何映射到原始向量?这是否意味着要复制2000000个向量,每个向量包含5-50个条目,或者反过来复制。您声明第二种情况是在80Mb传输上每秒传输2Gb。这与CUDA附带的标准HostToDevice带宽测试的性能相比如何?M行,N列。是的,Nvidia的visual profiler报告第二种情况的平均速度为2GB/s,我是否应该使用nvprof?。对于可分页内存传输测试,我得到了大约3.7GB/s,所以我可以说我得到了大约50%的可用带宽。如果你使用cudaEvents在这个特定的cudaMemcpy调用上运行你自己的带宽测量,你会得到什么样的传输速率?值得注意的是,固定主机内存不是免费的——这样做会带来相当高的API和主机内核开销。可能是,虽然使用固定内存的传输速度更快,但如果仅涉及一次传输,则代码的总体执行时间可能不会提高8Gb/s是PCIe 2.0 x16链路每个方向的峰值理论带宽。由于种种原因,它在实践中不可能实现。我从未见过一个测量值大大高于6GB/s,而6GB/s只能通过固定传输来实现。您不能期望在PCIe 2.0 x16上测量或观察到8GB/s的单向传输的实际数据负载。@罗伯特·克罗维拉:您完全正确,我编辑了答案以澄清这一点。值得注意的是,固定主机内存不是免费的-这样做会带来相当高的API和主机内核开销。可能是,虽然使用固定内存的传输速度更快,但如果仅涉及一次传输,则代码的总体执行时间可能不会提高8Gb/s是PCIe 2.0 x16链路每个方向的峰值理论带宽。由于种种原因,它在实践中不可能实现。我从来没有见过一个度量
数据传输速率远远高于6GB/s,只有通过固定传输才能实现6GB/s。您不能期望在PCIe 2.0 x16上测量或观察到8GB/s单向传输的实际数据有效负载。@罗伯特·克罗维拉:您完全正确,我编辑了答案以澄清这一点。
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)
);