使用NVIDIA Quadro M4000降低主机 - 设备传输速率

时间:2016-03-07 13:04:38

标签: opencl nvidia

我在安装在PCIe 3x16上的NVIDIA Quadro M4000上进行OpenCL。在卡片文档中,据说传输速率CPU-> GPU可以达到15.7Gb / s,而在我的基准测试中它只能产生~2.4Gb / s。我知道有效传输速率可能与理论传输速率有显着差异,但我并不期望差异那么大。

任何人都有使用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);
}

2 个答案:

答案 0 :(得分:1)

由于你的问题含糊不清,很难确定你表现不佳的确切原因。一些具体的代码可能帮助。

但是,在您的评论中,您说您转移了6220800浮点数组。这大约是200兆比特的转移。在最大传输速率(15.7Gb / s)下,应该提供大约12ms。

但是,对于每个新的转移请求,还会添加一个延迟,对于小转移,这会有效降低您的传输速率。

您是否尝试过对更大的阵列进行基准测试(例如,大小为100倍)?

答案 1 :(得分:1)

您正在使用阻止传输,这意味着您在读取/写入请求中会出现停顿(此外,您并未使用固定内存,但是您已解决此问题)。目前,您的代码

开始计时 - &gt;写 - &gt;摊位 - &gt;内核 - &gt;阅读 - &gt;摊位 - &gt;结束时间。如果传输比例大约为2ms,这将极大地影响内存带宽传输的时间,因为停顿的大小与此相当。如果要准确测量带宽,则需要消除这些停顿