データセンター プラットフォームでは、4K ページ境界に合わせてメモリを割り当てる方が効率的です。エンベデッド プラットフォームでは、連続的なメモリ割り当てを実行する方が効率的です。いずれの場合も、バッファーの作成時に XRT にホストメモリを割り当てることができます。これは、バッファーを作成するときに CL_MEM_ALLOC_HOST_PTR
フラグを使用し、
clEnqueueMapBuffer
を使用して割り当てられたメモリをユーザー空間ポインターにマッピングすると実行できます。この方法を使用する場合、4K 境界に揃えられたホスト空間ポインターを作成する必要はありません。
clEnqueueMapBuffer
API は指定したバッファーをマップして XRT で作成されたポインターをこのマップした領域に戻します。この後、ホスト側のポインターをユーザーのデータで埋めて、clEnqueueMigrateMemObject
でデータをデバイスに送信したり受信したりします。次は、この形式を使用したコード例です。
// Two cl_mem buffer, for read and write by kernel
cl_mem dev_mem_read_ptr = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
sizeof(int) * number_of_words, NULL, NULL);
cl_mem dev_mem_write_ptr = clCreateBuffer(context, CL_MEM_ALLOC_HOST_PTR | CL_MEM_WRITE_ONLY,
sizeof(int) * number_of_words, NULL, NULL);
cl::Buffer in1_buf(context, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY, sizeof(int) * DATA_SIZE, NULL, &err);
// Setting arguments
clSetKernelArg(kernel, 0, sizeof(cl_mem), &dev_mem_read_ptr);
clSetKernelArg(kernel, 1, sizeof(cl_mem), &dev_mem_write_ptr);
// Get Host side pointer of the cl_mem buffer object
auto host_write_ptr = clEnqueueMapBuffer(queue,dev_mem_read_ptr,true,CL_MAP_WRITE,0,bytes,0,nullptr,nullptr,&err);
auto host_read_ptr = clEnqueueMapBuffer(queue,dev_mem_write_ptr,true,CL_MAP_READ,0,bytes,0,nullptr,nullptr,&err);
// Fill up the host_write_ptr to send the data to the FPGA
for(int i=0; i< MAX; i++) {
host_write_ptr[i] = <.... >
}
// Migrate
cl_mem mems[2] = {host_write_ptr,host_read_ptr};
clEnqueueMigrateMemObjects(queue,2,mems,0,0,nullptr,&migrate_event));
// Schedule the kernel
clEnqueueTask(queue,kernel,1,&migrate_event,&enqueue_event);
// Migrate data back to host
clEnqueueMigrateMemObjects(queue, 1, &dev_mem_write_ptr,
CL_MIGRATE_MEM_OBJECT_HOST,1,&enqueue_event, &data_read_event);
clWaitForEvents(1,&data_read_event);
// Now use the data from the host_read_ptr
clEnqueueMapBuffer
を使用する例は、Vitis Examples GitHub リポジトリの Data Transfer (C) を参照してください。