編輯:根據評論中的討論,我高估了多少執行緒會有所幫助,并且已經回到Parallell.ForEach合理的狀態MaxDegreeOfParallelism,只需要等待它。
我有一個二維陣列資料結構,并對資料切片執行作業。同時處理所有資料只需要大約 1000 個執行緒。基本上所有約 7000 個資料點都有大約 1000 個“天”的資料,我想在一個新執行緒中并行處理每天的資料。
我的問題是在子執行緒中作業會大大減慢主執行緒啟動它們的時間。如果我沒有在子執行緒中完成任何作業,主執行緒基本上會立即啟動它們。在下面的示例中,只需做一些作業,啟動所有執行緒需要大約 65 毫秒。在我的實際用例中,作業執行緒將花費大約 5-10 秒來計算它們需要的所有內容,但我希望它們都立即啟動,否則,我基本上是按順序運行作業。我不明白為什么他們的作業會減慢主執行緒的啟動速度。
資料的設定方式無關緊要(我希望如此)。它的設定方式可能看起來很奇怪,我只是在模擬我如何接收資料。重要的是,如果您foreach在DoThreadWork方法中注釋掉回圈,啟動執行緒所需的時間會大大降低。
我有一個for (var i = 0; i < 4; i )回圈只是為了多次運行模擬以查看 4 組時序結果,以確保它不僅僅是第一次慢。
這是一個模擬我的真實代碼的代碼片段:
public static void Main(string[] args)
{
var fakeData = Enumerable
.Range(0, 7000)
.Select(_ => Enumerable.Range(0, 400).ToArray())
.ToArray();
const int offset = 100;
var dataIndices = Enumerable
.Range(offset, 290)
.ToArray();
for (var i = 0; i < 4; i )
{
var s = Stopwatch.StartNew();
var threads = dataIndices
.Select(n =>
{
var thread = new Thread(() =>
{
foreach (var fake in fakeData)
{
var sliced = new ArraySegment<int>(fake, n - offset, n - (n - offset));
DoThreadWork(sliced);
}
});
return thread;
})
.ToList();
foreach (var thread in threads)
{
thread.Start();
}
Console.WriteLine($"Before Join: {s.Elapsed.Milliseconds}");
foreach (var thread in threads)
{
thread.Join();
}
Console.WriteLine($"After Join: {s.Elapsed.Milliseconds}");
}
}
private static void DoThreadWork(ArraySegment<int> fakeData)
{
// Commenting out this foreach loop will dramatically increase the speed
// in which all the threads start
var a = 0;
foreach (var fake in fakeData)
{
// Simulate thread work
a = fake;
}
}
uj5u.com熱心網友回復:
使用執行緒/任務池并將執行緒/任務數限制2*(CPU Cores)為最多。創建更多執行緒并不會神奇地完成更多作業,因為您需要硬體“執行緒”來運行它們(非 SMT CPU 的每個 CPU 內核 1 個,Intel HT 的每個內核 2 個,AMD 的 SMT 實作)。執行成百上千個不必被動地等待異步回呼(即 I/O)的執行緒會使運行執行緒的效率大大降低,因為無緣無故地使用背景關系切換來顛簸 CPU。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/420778.html
標籤:
