アッププログラムのどの時点でも速度低下が見られるため、問題の根本は「スレッド化」ではないと思います。2 つのプロセッサを使用すると、おそらく 2 つのプロセッサが相互に「通信」する必要があるため、プログラムの実行が遅くなると思います。私はいくつかのテストを行う必要があります。プロセッサの 1 つを無効にして、何が起こるか見てみます。
====================================
これが C# の質問かどうかはわかりませんが、おそらくハードウェアに関するものですが、C# が最も適していると思います。
安価な DL120 サーバーを使用していましたが、より高価な 2 プロセッサの DL360p サーバーにアップグレードすることにしました。予想外に、私の C# プログラムは、数倍高速であるはずの新しいサーバーで約 2 倍遅く動作します。
約 60 の機器のFASTデータを処理しました。以下のように、インストゥルメントごとに個別のタスクを作成しました。
BlockingCollection<OrderUpdate> updatesQuery;
if (instrument2OrderUpdates.ContainsKey(instrument))
{
updatesQuery = instrument2OrderUpdates[instrument];
} else
{
updatesQuery = new BlockingCollection<OrderUpdate>();
instrument2OrderUpdates[instrument] = updatesQuery;
ScheduleFastOrdersProcessing(updatesQuery);
}
orderUpdate.Checkpoint("updatesQuery.Add");
updatesQuery.Add(orderUpdate);
}
private void ScheduleFastOrdersProcessing(BlockingCollection<OrderUpdate> updatesQuery)
{
Task.Factory.StartNew(() =>
{
Instrument instrument = null;
OrderBook orderBook = null;
int lastRptSeqNum = -1;
while (!updatesQuery.IsCompleted)
{
OrderUpdate orderUpdate;
try
{
orderUpdate = updatesQuery.Take();
} catch(InvalidOperationException e)
{
Log.Push(LogItemType.Error, e.Message);
continue;
}
orderUpdate.Checkpoint("received from updatesQuery.Take()");
......................
...................... // long not interesting processing code
}, TaskCreationOptions.LongRunning);
並行して実行できる約 60 のタスクがあるため、2 * E5-2640 (24 仮想スレッド、12 実スレッド) は 1 * E3-1220 (4 実スレッド) よりもはるかに高速に実行されるはずです。DL360p を使用して、タスク マネージャーで 95 個のスレッドを見つけたようです。DL120 を使用すると、55 スレッドしかありません。
しかし、DL120G7 の実行時間は 2 (!!) 倍高速です! E3-1220 のクロック レートは E5-2640 より少し優れています (3.1 GHz 対 2.5 GHz) が、私のコードは 2 * E5-2640 でより高速に動作するはずです。 2倍遅く動作すること!
タスク マネージャーで最大 50 スレッド = 平均 24 ~ 80 マイクロ秒
calling market.UpdateFastOrder = 23 updatesQuery.Add = 25 received from updatesQuery.Take() = 67 in orderbook = 80
calling market.UpdateFastOrder = 30 updatesQuery.Add = 32 received from updatesQuery.Take() = 64 in orderbook = 73
calling market.UpdateFastOrder = 31 updatesQuery.Add = 32 received from updatesQuery.Take() = 195 in orderbook = 204
calling market.UpdateFastOrder = 31 updatesQuery.Add = 32 received from updatesQuery.Take() = 74 in orderbook = 86
calling market.UpdateFastOrder = 18 updatesQuery.Add = 21 received from updatesQuery.Take() = 65 in orderbook = 78
calling market.UpdateFastOrder = 29 updatesQuery.Add = 32 received from updatesQuery.Take() = 76 in orderbook = 88
calling market.UpdateFastOrder = 30 updatesQuery.Add = 32 received from updatesQuery.Take() = 80 in orderbook = 92
calling market.UpdateFastOrder = 20 updatesQuery.Add = 21 received from updatesQuery.Take() = 65 in orderbook = 78
calling market.UpdateFastOrder = 21 updatesQuery.Add = 24 received from updatesQuery.Take() = 68 in orderbook = 81
calling market.UpdateFastOrder = 12 updatesQuery.Add = 13 received from updatesQuery.Take() = 58 in orderbook = 72
calling market.UpdateFastOrder = 22 updatesQuery.Add = 23 received from updatesQuery.Take() = 51 in orderbook = 59
calling market.UpdateFastOrder = 16 updatesQuery.Add = 16 received from updatesQuery.Take() = 20 in orderbook = 24
calling market.UpdateFastOrder = 28 updatesQuery.Add = 31 received from updatesQuery.Take() = 82 in orderbook = 94
calling market.UpdateFastOrder = 18 updatesQuery.Add = 21 received from updatesQuery.Take() = 65 in orderbook = 77
calling market.UpdateFastOrder = 29 updatesQuery.Add = 29 received from updatesQuery.Take() = 259 in orderbook = 264
calling market.UpdateFastOrder = 49 updatesQuery.Add = 52 received from updatesQuery.Take() = 99 in orderbook = 113
calling market.UpdateFastOrder = 22 updatesQuery.Add = 23 received from updatesQuery.Take() = 50 in orderbook = 60
calling market.UpdateFastOrder = 29 updatesQuery.Add = 32 received from updatesQuery.Take() = 76 in orderbook = 88
calling market.UpdateFastOrder = 16 updatesQuery.Add = 19 received from updatesQuery.Take() = 63 in orderbook = 75
calling market.UpdateFastOrder = 27 updatesQuery.Add = 27 received from updatesQuery.Take() = 226 in orderbook = 231
calling market.UpdateFastOrder = 15 updatesQuery.Add = 16 received from updatesQuery.Take() = 35 in orderbook = 42
calling market.UpdateFastOrder = 18 updatesQuery.Add = 21 received from updatesQuery.Take() = 66 in orderbook = 78
タスク マネージャーで最大 95 スレッド。最高 = 40 平均 ~ 150 マイクロ秒
calling market.UpdateFastOrder = 62 updatesQuery.Add = 64 received from updatesQuery.Take() = 144 in orderbook = 205
calling market.UpdateFastOrder = 27 updatesQuery.Add = 32 received from updatesQuery.Take() = 101 in orderbook = 154
calling market.UpdateFastOrder = 45 updatesQuery.Add = 50 received from updatesQuery.Take() = 124 in orderbook = 187
calling market.UpdateFastOrder = 46 updatesQuery.Add = 51 received from updatesQuery.Take() = 127 in orderbook = 162
calling market.UpdateFastOrder = 63 updatesQuery.Add = 68 received from updatesQuery.Take() = 137 in orderbook = 174
calling market.UpdateFastOrder = 53 updatesQuery.Add = 55 received from updatesQuery.Take() = 133 in orderbook = 171
calling market.UpdateFastOrder = 44 updatesQuery.Add = 46 received from updatesQuery.Take() = 131 in orderbook = 158
calling market.UpdateFastOrder = 37 updatesQuery.Add = 39 received from updatesQuery.Take() = 102 in orderbook = 140
calling market.UpdateFastOrder = 45 updatesQuery.Add = 50 received from updatesQuery.Take() = 115 in orderbook = 154
calling market.UpdateFastOrder = 50 updatesQuery.Add = 55 received from updatesQuery.Take() = 133 in orderbook = 160
calling market.UpdateFastOrder = 26 updatesQuery.Add = 50 received from updatesQuery.Take() = 99 in orderbook = 111
calling market.UpdateFastOrder = 14 updatesQuery.Add = 30 received from updatesQuery.Take() = 36 in orderbook = 40 <-- best one I can find among thousands
数倍高速なサーバーで私のプログラムが 2 倍遅く実行される理由がわかりますか? おそらく、~60 個のタスクを作成するべきではありませんか? おそらく、95 個のスレッドを使用するのではなく、50 個または 24 個に制限するように .NET に指示する必要がありますか? おそらく、これは 2 つのプロセッサと 1 つのプロセッサの構成の問題ですか? DL360P Gen8 のプロセッサの 1 つを無効にするだけで、プログラムが大幅に高速化されるのでしょうか?
追加した
- market.UpdateFastOrder の呼び出し - orderUpdate オブジェクトが作成されます
- updatesQuery.Add - orderUpdate は BlockingCollection に入れられます
- updatesQuery.Take() から受信 - BlockingCollection から削除された orderUpdate
- in orderbook - orderUpdated が解析されて orderBook に適用されます