【问题标题】:Low memory copy throughput Host to Device低内存复制吞吐量主机到设备
【发布时间】:2013-07-17 07:56:46
【问题描述】:

我有一个向量向量vector<vector<double>> data。 我只想复制该“二维矩阵”中包含的信息,因为 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。

【问题讨论】:

  • 你应该更准确 - 我认为你并不是说你的 memcpy 吞吐量很低,但是你的 cudaMemcpy 吞吐量很低,对吧?为了帮助您,您还应该说明您拥有哪个 GPU,实际吞吐量是多少,以及您的 M 和 N 的大小。
  • 对不起,我的意思是cudaMemcpy(我只是复制了 nvvp 分析器所说的内容)。我刚刚编辑了问题。
  • M和N如何映射到原始向量?这是否意味着您有 2000000 个向量,每个向量有 5-50 个条目要复制或反过来。您说第二种情况是在 80Mb 传输中为您提供每秒 2Gb/s 的传输。这与 CUDA 附带的标准 HostToDevice 带宽测试的性能相比如何?
  • M 行,N 列。是的,Nvidia 的视觉分析器报告第二种情况的平均速度为 2GB/s,我应该改用 nvprof 吗?对于可分页内存传输测试,我得到了大约 3.7GB/s,所以我可以说我得到了大约 50% 的可用带宽。
  • 如果您使用 cudaEvents 对这个特定的 cudaMemcpy 调用运行自己的带宽测量,您会获得什么样的传输速率?

标签: cuda gpgpu


【解决方案1】:

吞吐量缓慢的一个原因可能是您为双矩阵分配了新的。该内存没有页面锁定。您可以使用系统功能(不知道您使用哪个系统)或提供此功能的 cuda 功能。应该是cudaMallocHost。

只需删除您的=new double[M*N] 并将您的h_values 设置为cudaMallocHost(&amp;h_values, sizeof(double)*M*N)(当然不要删除它,而是释放它(使用cudaFreeHost))。

顺便说一句。理论最高速度为 8 GB/s(PCI 2.0 x 16 通道),实际上你会保持在它以下(大约 6 GB/s)。

【讨论】:

  • 值得注意的是,固定主机内存并不是免费的——这样做会产生相当高的 API 和主机内核开销。可能虽然使用固定内存的传输更快,但如果只涉及一次传输,则代码的整体执行时间可能不会提高
  • 8GB/s 是 PCIe 2.0 x16 链路(每个方向)的峰值理论带宽。由于各种原因,在实践中无法实现。我从未见过显着高于 6GB/s 的测量值,而 6GB/s 只能通过固定传输来实现。您不能期望在 PCIe 2.0 x16 上测量或观察到 8GB/s 的实际数据负载单向传输。
  • @Robert Crovella:您说的完全正确,我编辑了答案以使其清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-25
  • 2012-06-09
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多