我想确保以clEnqueueReadBuffer()
正确的方式确保如何确保将数据从GPU复制到主内存所需的时间。我有点怀疑clFinish()
确实做出了贡献。
我通过此
运行10000个浮点数的100x点积并测量时间 // 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和Java jdk 1.7在Ubuntu 12.04 64位上使用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]; "+
"}";
答案 0 :(得分:1)
测量将数据读回主机的时间的第一种方法是正确的。第二种方法包括一些计算时间。
您正在阅读的数据量为1000000 * sizeof(float) = 4MB
。如果这需要2毫秒,那么这意味着您将获得4MB/0.002s = 2 GB/s
的带宽。为什么你认为这太好了不可能?您的卡支持PCIe x16,其理论峰值带宽为8 GB / s(单向)。