インテル® FPGA SDK for OpenCL™プロ・エディション: プログラミング・ガイド

ID 683846
日付 4/01/2019
Public
ドキュメント目次

5.4.4. インテル® FPGA SDK for OpenCL™ チャネル拡張の実装における制約

OpenCL™アプリケーションへのチャネル実装には、一定のデザイン上の制約があります。

複数のチャネル呼び出しサイト

カーネルは、同じチャネルを複数回読み取ることが可能ですが、複数のカーネルが同じチャネルから読み取ることはできません。同様に、カーネルは同じチャネルに複数回書き込むことはできますが、複数のカーネルが同じチャネルに書き込むことはできません。
__kernel void k1() {
  read_channel_intel (channel1);
  read_channel_intel (channel1);
  read_channel_intel (channel1);
}
インテル® FPGA SDK for OpenCL™オフライン・コンパイラーは、次のコードをコンパイルすることができず、エラーが発生します。
__kernel void k1(){
  write_channel_intel (channel1, 1);
}

__kernel void k2() {
  write_channel_intel (channel1, 2);
}

フィードバック・チャネルとフィードフォワード・チャネル

カーネルのチャネルは、read_onlyまたはwrite_onlyのどちらかになります。同じチャネルに対して読み書きを行うカーネルのパフォーマンスは低下する可能性があります。

静的なインデックス化

インテル® FPGA SDK for OpenCL™ のチャネル拡張は、チャネルIDの配列へのインデックス化をサポートしますが、非効率なハードウェアにつながります。

次に例を示します。

channel int ch[WORKGROUP_SIZE];

__kernel void consumer()
{

    int gid = get_global_id(0);
    int value = read_channel_intel(ch[gid]);

    //statements
}

この例をコンパイルすると、次の警告メッセージが表示されます。

Compiler Warning: Dynamic access into channel array ch was expanded into predicated 
static accesses on every channel of the array.

アクセスが動的で、配列のチャネルのサブセットのみにアクセスできることが明確な場合は、switchステートメントを使用し、わずかに効率的なハードウェアを生成することができます。

channel int ch[WORKGROUP_SIZE];
 
__kernel void consumer() {
 
 int gid = get_global_id(0);
 int value;

 switch(gid)
 {
  case 0: value = read_channel_intel(ch[0]); break;

  case 2: value = read_channel_intel(ch[2]); break;
  case 3: value = read_channel_intel(ch[3]); break;
  //statements
	
	 case WORKGROUP_SIZE-1:read_channel_intel(ch[WORKGROUP_SIZE-1]); break;
 }

 //statements
}

カーネルのベクトル化に対するサポート

チャネルを使用するカーネルをベクトル化することはできません。したがって、カーネルコードにnum_simd_work_itemsカーネル属性を含めないでください。チャネルを使用するカーネルをベクトル化すると、同じカーネルで複数のチャネルアクセスが発生し、調停が必要になります。これはベクトル化の利点を無効にします。よってSDKのチャネル拡張はカーネルのベクトル化をサポートしません。

read_channel_intelおよびwrite_channel_intel呼び出しにおける命令レベルの並列処理

データの依存性がread_channel_intelwrite_channel_intel呼び出し間に存在しない場合、オフライン・コンパイラーはそれらの命令を並行して実行しようと試みます。その結果、オフライン・コンパイラーはこのread_channel_intelwrite_channel_intel呼び出しを、OpenCLカーネルコードに表現されているシーケンスとは異なる順序で実行する場合があります。

次のコードのシーケンスを例に示します。

in_data1 = read_channel_intel(channel1);
in_data2 = read_channel_intel(channel2);
in_data3 = read_channel_intel(channel3);

read_channel_intel呼び出し間にデータの依存性がないため、オフライン・コンパイラーはこれらを任意の順序で実行できます。