使用NVIDIA Quadro M4000降低主机 - 设备传输速率
我在安装在PCIe 3x16上的NVIDIA Quadro M4000上做OpenCL。在卡文档中,据说CPU-> GPU的传输速率可以达到15.7Gb/s,而在我的基准测试中,它只能达到〜2.4Gb/s。我知道有效的传输速率可能与理论传输速率有很大的不同,但我并没有预料到这种差异会非常大。使用NVIDIA Quadro M4000降低主机 - 设备传输速率
任何人都有关于quadro CPU-> GPU数据传输的经验。
感谢
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<cmath>
#include<CL/cl.h>
#include <Windows.h>
using namespace std;
SYSTEMTIME last_call;
cl_platform_id platform_id = NULL;
cl_uint ret_num_platform;
cl_device_id device_id = NULL;
cl_uint ret_num_device;
cl_context context = NULL;
cl_command_queue command_queue = NULL;
cl_program program = NULL;
cl_kernel kernel = NULL;
cl_int err;
void _profile(char* msg){
SYSTEMTIME tmp;
clFinish(command_queue);
GetSystemTime(&tmp);
printf("__Profile --- %s --- : %d : %d : %d\n", msg, (tmp.wMinute - last_call.wMinute),
(tmp.wSecond - last_call.wSecond),
(tmp.wMilliseconds - last_call.wMilliseconds));
last_call = tmp;
}
int main()
{
// Reading Kernel Program
char *kernel_src_std = "__kernel void copy(__global const uchar *x, __global uchar *z){\
const int id = get_global_id(0);\
z[id] = x[id]; \
}";
size_t kernel_src_size = strlen(kernel_src_std);
// Create Input data
int w = 1920;
int h = 1080;
int c = 3;
float* input = (float*)malloc(w * h * c * sizeof(float));
for(int i=0;i<w*h*c;i++)
input[i] = (float)rand()/RAND_MAX;
// getting platform ID
err = clGetPlatformIDs(1, &platform_id, &ret_num_platform);
// Get Device ID
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, &ret_num_device);
// Create Context
context = clCreateContext(NULL,1,&device_id,NULL,NULL,&err);
// Create Command Queue
command_queue = clCreateCommandQueue(context, device_id, 0, &err);
// Create buffer Object
cl_mem buf_in = clCreateBuffer(context,CL_MEM_READ_ONLY, sizeof(float) * w*h*c,
0, &err);
cl_mem buf_out = clCreateBuffer(context,CL_MEM_WRITE_ONLY, sizeof(float) * w*h*c,
0, &err);
_profile("Start transfer input...");
// Copy Data from Host to Device
cl_event event[5];
err = clEnqueueWriteBuffer(command_queue,buf_in,CL_TRUE, 0, sizeof(float)*w*h*c,input,0,NULL, NULL);
_profile("End transfer input...");
// Create and Build Program
program = clCreateProgramWithSource(context, 1, (const char **)&kernel_src_std, 0, &err);
// Create Kernel
kernel = clCreateKernel(program,"copy",&err);
// Set Kernel Arguments
err = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&buf_in);
err = clSetKernelArg(kernel, 1,sizeof(cl_mem), (void *)&buf_out);
// Execute Kernel
size_t ws[]={h*w*c};
size_t lws[]={100};
err = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, ws, lws, 0, NULL, NULL);
// Create output buf
float* output = (float*)malloc(sizeof(float)*w*h*c);
// Read output Data, from Device to Host
err = clEnqueueReadBuffer(command_queue, buf_out, CL_TRUE, 0, sizeof(float)*w*h*c, output,NULL,NULL,NULL);
//Release Objects
clReleaseMemObject(buf_in);
clReleaseMemObject(buf_out);
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(command_queue);
clReleaseContext(context);
free(input);
free(output);
while(1);
return(0);
}
至于你的问题是模糊的,很难找出你表现不佳的确切原因。一些具体代码可能帮助。
但是,在你的评论中,你说你转移了一个6220800浮点数组。这大约是200兆转移。以最大传输速率(15.7Gb/s)应该可以提供大约12ms。
但是,随着每个新的传输请求,还有一个延迟被添加,这对于小的传输---可以有效地降低您的传输速率。
你有没有尝试过对数组进行基准测试(比如,尺寸是100x)?
对不起,我错过了类型:传输速率实际上是15.7GB/s(而不是Gb/s)。所以预期的转换时间应该是〜1.7ms。 我尝试过更大的阵列(100x),仍然有相同的速度。 这是我用于传输的一段代码: 'result = clEnqueueWriteBuffer(cl.command_queue,kernel.kernel_inputs [i] .data,CL_TRUE,0,sizeof(float)* kernel.kernel_inputs [i] .size ,kernel.inputs [i] .data,0,NULL,NULL);' 谢谢 – lity
你无法用阻塞调用和在CPU端测量传输速度。你应该使用clEvents。这种测量方式是虚假的,可能会给您任何结果,具体取决于触发回调时CPU和GPU之间的延迟。 – DarkZeros
我想你可以。在NVDIA OpenCL最佳实践中,它在opencl blocking命令调用上使用CPU定时器是所提出的两种剖析方法之一(2.1章) – lity
您正在使用阻塞传输,这意味着您在读取/写入请求时出现停顿(此外,您并未使用固定内存,但是解决了这个问题)。目前,您的代码为
开始计时 - >写入 - >停止 - >内核 - >读取 - >停止 - >结束计时。如果您的传输范围大约为2ms,这将大大影响您的内存带宽传输时间,因为这些档位在尺寸上与此相当。如果要精确测量带宽,则需要消除这些停顿。
它可能取决于您如何传输数据。你怎么做呢?它只是一个巨大的阵列,你转移到GPU?另外:您是否将您的结果与CUDA示例中给出的基准进行了比较? – CygnusX1
是的,我正在传输一个6220800浮点数组。这可能是原因吗?我无法在我的安装中找到OpenCL示例。人们似乎认为NVIDIA不再维护这些产品。我使用clEnqueueWriteBuffer进行传输。 – lity
@lity这个问题似乎是关于OpenCL,但也被标记为[cuda]。我建议删除该标签以避免混淆。确保该卡插入PCIe x16插槽,而不是PCIe x4插槽。对于传输大小> = 16 MB,PCIe gen3 x16的最大实际传输速率约为11-12 GB/sec。您需要在主机上使用“固定内存”以获得最高传输速度,但不确定OpenCL是否支持该功能。 – njuffa