OpenCLコンパイラが最適化するために生成するマシンコードを理解しようとしています。したがって、ツールm2s-opencl-kc(multi2simから)を使用して* .clファイルをオフラインコンパイルし、中間ファイル(スイッチ:-a)を*.isaファイルとして保持しました。この*.isaには、私が探しているもののように見える「分解」セクションが含まれています...
注:私のアセンブリの知識は少し「古い」ものです。Pentium386/486CPUなどの古いCPU用のアセンブリを作成しました。ですから、私は実際にベクトル命令を読むのに問題がありますが、それらについての理論的な知識はあります。
[... OTHER STUFF ... ]
; -------- Disassembly --------------------
00 ALU_PUSH_BEFORE: ADDR(32) CNT(6) KCACHE0(CB2:0-15) KCACHE1(CB0:0-15)
0 x: MOV R2.x, 0.0f
z: SETGT_INT R0.z, 1, KC0[0].y
t: MULLO_INT ____, R1.x, KC1[1].x
1 w: ADD_INT ____, R0.x, PS0
2 y: ADD_INT R2.y, PV1.w, KC1[6].x
3 x: PREDE_INT ____, R0.z, 0.0f UPDATE_EXEC_MASK UPDATE_PRED
01 JUMP POP_CNT(1) ADDR(9)
02 ALU: ADDR(38) CNT(5) KCACHE0(CB1:0-15)
4 x: MOV R2.x, 0.0f
y: MOV R3.y, 0.0f
w: LSHL ____, R2.y, 2
5 z: ADD_INT R2.z, KC0[0].x, PV4.w
03 LOOP_DX10 i0 FAIL_JUMP_ADDR(8)
04 ALU: ADDR(43) CNT(11) KCACHE0(CB2:0-15)
6 y: ADD_INT R3.y, R3.y, 1
w: LSHL ____, R3.y, 2
7 x: SETGT_INT R3.x, KC0[0].y, PV6.y
z: ADD_INT ____, R2.z, PV6.w
w: ADD_INT ____, PV6.w, 8
8 x: ASHR R0.x, PV7.w, 4
y: LSHR R0.y, PV7.z, 2
z: BFE_UINT R0.z, PV7.w, 0x00000002, 0x00000002
[... some more ... ]
私が疑問に思っているのは、コマンドの前にある数字と文字の意味です。私が理解したように、コンパイラはいくつかの「複雑な」命令を次のように生成しました。
00 ALU_PUSH_BEFORE: ADDR(32) CNT(6) KCACHE0(CB2:0-15) KCACHE1(CB0:0-15)
(質問:それはいわゆる「VeryLong InstructionWord」ですか?)
そして、この「複雑な」命令は、次のような複数の「単純な」命令で構成されています。
0 x: MOV R2.x, 0.0f
z: SETGT_INT R0.z, 1, KC0[0].y
t: MULLO_INT ____, R1.x, KC1[1].x
1 w: ADD_INT ____, R0.x, PS0
2 y: ADD_INT R2.y, PV1.w, KC1[6].x
3 x: PREDE_INT ____, R0.z, 0.0f UPDATE_EXEC_MASK UPDATE_PRED
これらの「単純な」命令は、各ベクトル単位の命令のようです。4つのベクトル単位は、x、y、z、およびwによって参照されます。しかし、「t」とは何ですか?それは別のベクトル単位ですか?「サイプレス」GPU用にコンパイルしました...
さて、数字について...これらは「行番号」のようなものですか?先行ゼロ:複素数命令のシリアル番号...?先行ゼロなし:単純命令のシリアル番号...?
メモリアクセスの待機状態がないと仮定すると、同じシリアルを持つすべての「単純な」命令を1サイクルで「論理的に」実行できると思います。たとえば、(上記の複雑な命令の)次の命令はサイクル0で「実行」されます。
0 x: MOV R2.x, 0.0f
z: SETGT_INT R0.z, 1, KC0[0].y
t: MULLO_INT ____, R1.x, KC1[1].x
「実行された」とは、ある種の(たとえば4サイクルの)パイプライン処理があることを意味します。これは、上記の命令がサイクル0で実行を開始し、サイクル3の後に終了する必要があることを意味します。
パイプラインに関する質問
次の命令(「1」など)がレジスタR2.xを読み取るとどうなりますか?それはR2.xの古い値(命令「0」の前)を読み取るのでしょうか、それとも命令「0」が終了するまで命令「1」を遅らせるのでしょうか?それとも、これは「気にしない」状況(未定義の結果を生成する)であり、コンパイラーがこれが決して起こらないように注意しなければならない状況ですか?
メモリアクセスに関する質問
レジスタへのアクセスは、データフェッチサイクル中に待たずに実行できると思います。メモリアクセスには、アクセスするメモリの種類に応じて、追加のサイクルが必要になります。
- 「__private」メモリは、ほとんどがレジスタにマップされている必要があります。
- __ローカルメモリ(同じグループの作業項目間で最大64KBを共有):現在のGPUで何サイクル余分に期待する必要がありますか?
- __グローバルメモリ:これは、たとえば256MBからxGBの外部DRAMである必要があります。ここで何サイクル余分に期待する必要がありますか?私の知る限り、このメモリはGPUデバイス用にキャッシュされていません。
- __定数メモリは__グローバルメモリのようにする必要がありますが、__ローカルメモリを使用してキャッシュされます
「ISA」の良いチュートリアルはありますか?
よろしく、ステファン