1

C++ オブジェクトのツリーを構築する従来の C++ アプリケーションがあります。LLVM を使用してクラス コンストラクターを呼び出し、上記のツリーを作成したいと考えています。生成された LLVM コードは非常に単純で、次のシーケンスが繰り返されているように見えます。

; ...
%11 = getelementptr [11 x i8*]* %Value_array1, i64 0, i64 1
%12 = call i8* @T_string_M_new_A_2Pv(i8* %heap, i8* getelementptr inbounds ([10 x i8]* @0, i64 0, i64 0))
%13 = call i8* @T_QueryLoc_M_new_A_2Pv4i(i8* %heap, i8* %12, i32 1, i32 1, i32 4, i32 5)
%14 = call i8* @T_GlobalEnvironment_M_getItemFactory_A_Pv(i8* %heap)
%15 = call i8* @T_xs_integer_M_new_A_Pvl(i8* %heap, i64 2)
%16 = call i8* @T_ItemFactory_M_createInteger_A_3Pv(i8* %heap, i8* %14, i8* %15)
%17 = call i8* @T_SingletonIterator_M_new_A_4Pv(i8* %heap, i8* %2, i8* %13, i8* %16)
store i8* %17, i8** %11, align 8
; ...

T_関数は、C++ コンストラクターを呼び出す C の「サンク」です。たとえば、次のようになります。

void* T_string_M_new_A_2Pv( void *v_value ) {
  string *const value = static_cast<string*>( v_value );
  return new string( value );
}

もちろんサンクは必要です。LLVM は C++ について何も知らないからです。機能は、 を介して使用中の に追加T_されます。ExecutionEngineExecutionEngine::addGlobalMapping()

このコードを JIT すると、JIT 自体のパフォーマンスが非常に悪くなります。を使用してコールグラフを生成しましたkcachegrind。私はすべての数字を理解しているわけではありません (この PDF にはコンマが含まれていないようです) が、左のフォークを見ると、下の 2 つの楕円Schedule...は 16K 回とsetHeightToAtLeas...呼ばれ、37K 回と呼ばれています。右側のフォークでRAGreed...は、35K 回呼び出されます。

ほとんどが単純なcallLLVM 命令のシーケンスであるにもかかわらず、これらは呼び出しが多すぎます。何かがひどく間違っているようです。

JIT'ing のパフォーマンスを改善する方法についてのアイデアはありますか?

4

1 に答える 1

0

JIT の動作方法に大きな変更を加えたり、JIT しようとしている特定の呼び出しを確認したりしなければ、もう 1 桁大きくなる可能性はほとんどありません。llc -O0 (例: llc -O0 -fast-isel-verbose mymodule.[ll,bc]) で -fast-isel-verbose を有効にすると、命令生成のために選択 DAG にフォールバックしているかどうかがわかります。もう一度プロファイリングして、現在のホット スポットを確認することをお勧めします。

于 2012-11-14T01:08:53.380 に答える