24
Altera SDK for OpenCL解体新書 ホストとデバイスの関係 2016.06.12() @Vengineer

Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

Embed Size (px)

Citation preview

Page 1: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

Altera SDK for OpenCL解体新書

ホストとデバイスの関係

2016.06.12(金)

@Vengineer

Page 2: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホストとデバイスの関係(PCIeデバイス)

PCIeデバイスの場合は、下記のような構成になる

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−A

Kernel−B

Kernel−C

DMA

PCIe PCIe

DMA

Page 3: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

Altera SDK for OpenCLでのBSPとは?

CPU

ホスト側のメモリ

Kernel−A

Kernel−B

Kernel−C

DMA

PCIe PCIe

DMABSPに相当する部分

デバイス側のメモリ

MIF

Page 4: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

生成されるHDLコード

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−A

Kernel−B

Kernel−C

DMA

PCIe PCIe

DMAaocが生成するHDLコード

MIF

Page 5: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

例題:vector addition

https://www.olcf.ornl.gov/tutorials/opencl-vector-addition/

double a[N], b[N], c[N];

vector_add( a, b, c, N );

void vector_add( double* a, double* b, double* c, const unsigned int n ){ for( unsigned int i=0 ; i<n ; i++ ) c[i] = a[i] + b[i];}

Page 6: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

デバイス側のOpenCLコード

const char *kernelSource = #pragma OPENCL EXTENSION cl_khr_fp64 : enable _kernel void vecAdd(__global double *a, __global double *b,             __global double *c, const unsigned int n) {

//Get our global thread ID int id = get_global_id(0);

//Make sure we do not go out of bounds if (id < n)

c[id] = a[id] + b[id]; }

Page 7: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホスト側のCコード(メモリの割当)

h_a = (double*)malloc(bytes);h_b = (double*)malloc(bytes);h_c = (double*)malloc(bytes); d_a = clCreateBuffer(context, CL_MEM_READ_ONLY, bytes, NULL, NULL);d_b = clCreateBuffer(context, CL_MEM_READ_ONLY, bytes, NULL, NULL);d_c = clCreateBuffer(context, CL_MEM_WRITE_ONLY , bytes, NULL, NULL);

Page 8: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホスト側のCコード(実行部)

err = clEnqueueWriteBuffer(queue, d_a, CL_TRUE, 0, bytes, h_a, 0, NULL, NULL);err |= clEnqueueWriteBuffer(queue, d_b, CL_TRUE, 0, bytes, h_b, 0, NULL, NULL); err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_a);err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_b);err |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &d_c);err |= clSetKernelArg(kernel, 3, sizeof(unsigned int), &n); err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalSize, &localSize, 0, NULL, NULL); clFinish(queue); clEnqueueReadBuffer(queue, d_c, CL_TRUE, 0, bytes, h_c, 0, NULL, NULL );

Page 9: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホスト側のCコード(メモリの開放)

clReleaseMemObject(d_a); clReleaseMemObject(d_b); clReleaseMemObject(d_c);

free(h_a);free(h_b);free(h_c);

Page 10: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

処理フロー

1) ホスト側のメモリからデバイス側のメモリにデータを移動

clEnqueueWriteBuffer2) カーネルへのパラメータ設定

  clSetKernelArg3) カーネルを実行

clEnqueueTask / clEnqueuNDRangeKernel4) カーネルの終了待ち

clFinish5) デバイス側のメモリからホスト側のメモリにデータを移動

  clEnqueueReadBuffer

Page 11: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

clEnqueuWriteBuffer

ホスト側のメモリからデバイス側のメモリへデータを移動する

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−BDMA

PCIe PCIe

DMA

Page 12: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

clSetKernelArg

カーネルへのパラメータ設定

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−BDMA

PCIe PCIe

DMA

Page 13: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

clEnqueuTask / clEnqueueNDRageKernel

カーネルの実行

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−BDMA

PCIe PCIe

DMA

Page 14: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

clFinish

カーネルの終了待ち

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−BDMA

PCIe PCIe

DMA

Page 15: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

clEnqueuReadBuffer

デバイス側のメモリからホスト側のメモリへデータを移動する

CPU

ホスト側のメモリ

デバイス側のメモリ

Kernel−BDMA

PCIe PCIe

DMA

Page 16: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

実行時間

CPUの実行時間に比べて、FPGAの実行時間が短くならないと

FPGAでのアクセレーションは意味が無い!

FPGAの実行時間 = 1) + 2) + 3) + 4) + 5)

 1) ホスト側のメモリからデバイス側のメモリにデータを移動

 2) カーネルへのパラメータ設定

 3) カーネルを実行

 4) カーネルの終了待ち

 5) デバイス側のメモリからホスト側のメモリにデータを移動

Page 17: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホストとデバイスの関係(SoCデバイス)

SoCデバイスの場合は、下記のような構成になる

CPU

ホスト側のメモリ

Kernel−A

Kernel−B

Kernel−C

PCIeデバイスでは必要だった、データ移動のためのDMAがない

Page 18: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホスト側のCコード(メモリの割当)

cl_mem d_a = clCreateBuffer(context,CL_MEM_ALLOC_HOST_PTR, bytes, NULL, NULL);cl_mem d_b = clCreateBuffer(context,CL_MEM_ALLOC_HOST_PTR, bytes, NULL, NULL);cl_mem d_c = clCreateBuffer(context,CL_MEM_ALLOC_HOST_PTR, bytes, NULL, NULL);

// clEnqueuWriteBuffer/clEnqueueReadBufferの代わりにclEnqueueMapBufferが必要(ホスト側のメモリをマップする)

double *h_a = (double*)clEnqueueMapBuffer (queue, d_a, CL_TRUE, CL_MAP_READ, 0, bytes, 0, NULL, NULL );double *h_b = (double*)clEnqueueMapBuffer (queue, d_b, CL_TRUE, CL_MAP_READ, 0, bytes, 0, NULL, NULL );double *h_c = (double*)clEnqueueMapBuffer (queue, d_c, CL_TRUE, CL_MAP_WRITE, 0, bytes, 0, NULL, NULL );

Page 19: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホスト側のCコード(実行部)

err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &d_a);err |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &d_b);err |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &d_c);err |= clSetKernelArg(kernel, 3, sizeof(unsigned int), &n); err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, &globalSize, &localSize, 0, NULL, NULL); clFinish(queue);

Page 20: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

ホスト側のCコード(メモリの開放)

// clEnqueueUnMapMemObjectが必要clEnqueueUnmapMemObject(queue, d_a, h_a, 0, NULL, NULL );clEnqueueUnmapMemObject(queue, d_b, h_b, 0, NULL, NULL );clEnqueueUnmapMemObject(queue, d_c, h_c, 0, NULL, NULL );

clReleaseMemObject(d_a); clReleaseMemObject(d_b); clReleaseMemObject(d_c);

// ホスト側のメモリ開放は必要なし

Page 21: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

メモリ割当の違い

PCIeデバイス

 ホスト側のメモリ割当

 デバイス側のメモリ割当

  ....

 デバイス側のメモリ開放

 ホスト側のメモリ開放

SoCデバイス

 デバイス側のメモリ割当

 ホスト側のメモリマッピング

  ....

 ホスト側のメモリアンマッピング

 デバイス側のメモリ開放

Page 22: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

SoCデバイスでは、CMAを使う

CPU

ホスト側のメモリ

Kernel−A

Kernel−B

Kernel−C

ホスト側のメモリの一部をデバイス側のメモリとして使用し、CPU側からアクセスできるようにマップする

Linuxをブートするときに、引数として、cma=128M のようにして事前に割り当てる

CMA(Continuous Memory Allocator)ただし、CPUからは非キャッシュ領域

参考資料)、https://aelseb.wordpress.com/2015/04/11/contiguous-memory-on-arm-and-cache-coherency/

Page 23: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

実行時間

CPUの実行時間に比べて、FPGAの実行時間が短くならないと

FPGAでのアクセレーションは意味が無い!

FPGAの実行時間 = 1) + 2) + 3) + 4) + 5)

 1) CPUがCMA領域(非キャッシュ領域)のメモリにデータを書き込む

 2) カーネルへのパラメータ設定

 3) カーネルを実行

 4) カーネルの終了待ち

 5) CPUがCMA領域(非キャッシュ領域)のメモリからデータを読み込む

Page 24: Altera SDK for OpenCL解体新書 : ホストとデバイスの関係

おしまい