【发布时间】:2011-10-12 19:46:35
【问题描述】:
我和一位同事正在集思广益,讨论如何减少主机和设备之间的内存传输时间,结果可能将事情安排到一次超大传输(即一次调用)可能会有所帮助。这导致我创建了一个测试用例,我在其中计算了传输少量大数据块与许多小数据数据块的时间。我得到了一些非常有趣/奇怪的结果,想知道这里有没有人解释一下?
我不会把我的整个代码放在这里,因为它很长,但我用两种不同的方式测试了分块:
-
显式写出所有 cudaMemcpy,例如:
cudaEventRecord(开始, 0);
cudaMemcpy(aD, a, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 1*nBytes/10, a + 1*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 2*nBytes/10, a + 2*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 3*nBytes/10, a + 3*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 4*nBytes/10, a + 4*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 5*nBytes/10, a + 5*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 6*nBytes/10, a + 6*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 7*nBytes/10, a + 7*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 8*nBytes/10, a + 8*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaMemcpy(aD + 9*nBytes/10, a + 9*nBytes/10, nBytes/10, cudaMemcpyHostToDevice);
cudaEventRecord(停止, 0);
cudaEventSynchronize(停止);
cudaEventElapsedTime(&time, start, stop); -
将 cudaMemcpy 放入 for 循环:
cudaEventRecord(开始, 0);
for(int i = 0; i {
cudaMemcpy(aD + i*nBytes/nChunks, a + i*nBytes/nChunks, nBytes/nChunks, cudaMemcpyHostToDevice);
}
cudaEventRecord(停止, 0);
cudaEventSynchronize(停止);
cudaEventElapsedTime(&time, start, stop);
需要注意的是,为了以防万一,我还在每次测试开始时进行了“热身”传输,尽管我认为不需要它(上下文是由 cudaMalloc 调用创建的)。
我在从 1 MB 到 1 GB 的总传输大小上对此进行了测试,其中每个测试用例传输相同数量的信息,而不管它是如何分块的。我的输出示例如下:
单次大传输 = 0.451616 ms
10 次显式传输 = 0.198016 毫秒
100 次显式传输 = 0.691712 毫秒
10 次循环传输 = 0.174848 毫秒
100 次循环传输 = 0.683744 毫秒
1000 次循环传输 = 6.145792 毫秒
10000 次循环传输 = 104.981247 毫秒
100000 次循环传输 = 13097.441406 毫秒
这里有趣但我没有得到的是,总体而言,10 次传输总是比其他任何传输都快很多,即使是单次大传输!无论数据集有多大或多小,该结果都保持一致(即 10x100MB 与 1x1GB 或 10x1MB 与 1x10MB 仍然会导致 10 倍更快)。如果有人对为什么会这样或者我可能做错了什么得到这些奇怪的数字有任何见解,我很想听听你要说什么。
谢谢!
附:我知道 cudaMemcpy 带有隐式同步,所以我可以使用 CPU 计时器,而 cudaEventSynchronize 是多余的,但我认为最好还是安全一点
更新:我编写了一个函数来尝试利用性能时空连续体中这种明显的裂痕。但是,当我使用该函数时,该函数在我的测试用例中编写为 EXACLTY,效果消失了,我看到了我所期望的(单个 cudaMemcpy 是最快的)。也许这更像是量子物理学而不是相对论,其中观察行为会改变行为......
【问题讨论】:
-
nChunks 是在运行时还是编译时设置的变量?
-
嗯,nChunks 是一个在每个循环之前设置的变量,例如nChunks = 100;那是运行时,对吧?
-
P.S.我在 Tesla M2050 上运行,它的计算能力为 2.0
-
这是在 WDDM windows 平台(Vista、7 还是 server 2008?)上完成的?
-
不,Linux Red Hat 4.1.2。