2016-07-11 6 views
1

Deedleを使用してマルチスレッドのC#サービスを扱っています。クアッドコアの現在のシステムとオクタコアのターゲットシステムのテストでは、サービスの速度がターゲットシステムの速度の2倍ではなく、約2倍遅くなっています。スレッド数を2に制限しても、ターゲットシステムはまだ40%遅くなります。より良いシステムでマルチスレッドパフォーマンスが悪化する可能性があります(恐らくDeedleのため)

分析ではDeedle(/ F#)で多くの待機が行われ、ターゲットシステムは基本的に2つのコアで実行されます。ノンディドルテストプログラムは、通常の動作を示し、ターゲットシステム上のメモリ帯域幅を上回ります。

これを引き起こす可能性のあることや、この状況に最も近づく方法については、

EDIT:Invokeの呼び出しで待機する時間がほとんどのようです。

+0

私はDeedleがプログラムの実行を遅らせる洗練されたスレッド同期を行っていないと思っていますが、複数のスレッドから同じフレーム/シリーズにアクセスしている場合、CPUキャッシュに影響する可能性があります並列化のオーバーヘッドは、並列化の利点よりも大きくなります。 –

+0

@TomasPetricek私たちの使い方については、スレッドはかなり独立していると見なすことができます。もちろん、図書館で何が起こるか(あるいはCLRではさらに深いこと)は言うことができません。私が測定できた限り(例えば、インテルのPCMで)、キャッシングは問題ではありません。奇妙なことは、(両方のシステムで)スレッドの数を制限するときに、少なくとも現在のシステムと同様に実行することを期待することです。 – mweerden

+0

スレッドに余計なことがなくなればすぐにスレッドをアイドル状態にするのに十分なスリープステートメントがコード内にありますか?スレッドが競合しているようですが、休憩をとることなくループしているだけでしょうか? –

答えて

1

この問題は、Windows 7、.NET 4.5(または実際には4.0ランタイム)とF#/ Deedleでのテール再帰の多用を組み合わせたものであることが判明しました。

Visual Studioの並行処理ビジュアライザを使用して、Invoke呼び出しで待機する時間が最もかかっていることがわかりました。精密検査では、次のコールトレースでこれらの結果:

ntdll.dll:RtlEnterCriticalSection 
ntdll.dll:RtlpLookupDynamicFunctionEntry 
ntdll.dll:RtlLookupFunctionEntry 
clr.dll:JIT_TailCall 
<some Deedle/F# thing>.Invoke 

これらの機能を検索するには、F#を使用すると、JIT_TailCallへの呼び出しの多くにつながることを示す複数の記事やフォーラムのスレッドを与え、その.NET 4.6は、新しいを持っていますJITコンパイラは、これらの呼び出しに関連するいくつかの問題に対処しているようです。ロック/同期に関連する問題に言及しているものは見つかりませんでしたが、.NET 4.6へのアップデートが解決策であるという考えが私に与えられました。

ただし、.NET 4.5も使用している自分のWindows 8.1システムでは、この問題は発生しません。同様の呼び出しコールのビットを検索した後、私は次のように、このシステム上のコールトレースが見えたことがわかった:

ntdll.dll:RtlAcquireSRWLockShared 
ntdll.dll:RtlpLookupDynamicFunctionEntry 
ntdll.dll:RtlLookupFunctionEntry 
clr.dll:JIT_TailCall 
<some Deedle/F# thing>.Invoke 

はどうやら、Windowsの8(0.1)にロック機構がもたらした、あまり厳密なものに変更されましたロックを待つ必要があまりありません。

Windows 7の厳密なロックと.NET 4.5の非効率なJITコンパイラの両方のターゲットシステムの組み合わせでのみ、F#の大量のテール再帰が問題を引き起こしました。 .NET 4.6にアップデートした後、問題は消え、私たちのサービスは期待どおりに動作しています。

関連する問題