我想确保 clEnqueueReadBuffer()
的测量时间如何测量将数据从 GPU 复制到主内存所需的时间的正确方法。我有点怀疑clFinish()
也确实做出了贡献。
我运行 1000000 个 float 的 100 倍点积,并以此测量时间
// RUN TIME BLOCK
println( " Running OpenCL program ... " );
t1 = System.nanoTime();
for (int reps = 0; reps < 100; reps++) {
clEnqueueNDRangeKernel(commandQueue, kernel, 1, null, global_work_size, local_work_size, 0, null, null);
}
clFinish(commandQueue); // VERSION 1
t2 = System.nanoTime();
println( " OpenCL Run Time : "+ ((t2-t1)*1e-9)+" [s] " );
// READ OUT TIME BLOCK
t1 = System.nanoTime();
//clFinish(commandQueue); // VERSION 2
clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE, 0, n * Sizeof.cl_float, dst, 0, null, null);
t2 = System.nanoTime();
println( " Read-out Time: "+ ((t2-t1)*1e-9)+" [s] " );
得到结果
OpenCL Run Time : 2.5124469 [s]
Read-out Time: 0.002145424 [s]
这对我来说似乎有点太好了,只有 2 毫秒和 < 总时间的 0.1% ... CPU-GPU 通信瓶颈的问题似乎并没有那么严重。
当我输入clFinish(commandQueue);
时里面Read-out Time
阻止我得到这些结果
OpenCL Run Time : 1.0892084 [s]
Read-out Time: 1.4300439 [s]
另一方面,这似乎太糟糕了……在 GPU 上执行 100 次乘法比通过 PCI-express 复制要快? ....也许吧
<小时/>只是为了完整性:
我用了openclp5 processing 的库其中使用 jocl在 Ubuntu 12.04 64 位上使用 Java jdk 1.7,配备 Quadro FX 580 GPU 和
我的内核很简单(没有优化或任何东西)
String programSource =
"__kernel void sampleKernel( "+
"__global const float *a, __global const float *b, __global float *c) { "+
" int gid = get_global_id(0); "+
" c[gid] = a[gid] * b[gid]; "+
"}";
最佳答案
您测量将数据读回主机的时间的第一种方法是正确的。第二种方法需要一些计算时间。
您正在读取的数据量为1000000 * sizeof(float) = 4MB
。如果这需要 2 毫秒,则意味着您将获得 4MB/0.002s = 2 GB/s
的带宽。为什么你认为这好得令人难以置信?您的卡支持 PCIe x16,理论峰值带宽为 8 GB/s(单向)。
关于java - 如何测量 OpenCL 读出时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24120298/