我對并行編程相當陌生;我正在開發一個處理不同基數的程式,我想并行化加法方法。
首先,它計算線性卷積并稍后進行進位,因此for回圈的每次迭代都是獨立的(示例):
(Little Endianness btw) [2,7,1] [8,7,5] = [10,14,6] => [0,5,7]
問題是,如果有可用的執行緒,我是否可以通過在不同執行緒中同時完成迭代來加快添加程序,以及如何?
uj5u.com熱心網友回復:
如果陣列很大(執行緒有自己的開銷),您可以嘗試Parallel,例如Parallel.For:
int[] left = ...
int[] right = ...
int[] result = new int[left.Length];
...
Parallel.For(0, left.Length, i => result[i] = left[i] right[i]);
我們來看看效果:
int N = 100_000_000;
int[] left = new int[N];
int[] right = new int[N];
int[] result = new int[left.Length];
// To prevent garbage collection while testing
GC.Collect(2);
Stopwatch sw = new Stopwatch();
sw.Start();
// Parallel version
//Parallel.For(0, left.Length, i => result[i] = left[i] right[i]);
// Standard for loop version
for (int i = left.Length - 1; i >= 0; --i)
result[i] = left[i] right[i];
sw.Stop();
Console.Write(sw.ElapsedMilliseconds);
結果(.Net 6 IA-64、Realease build、Core i9、6 核)
200 - parallel version
500 - for loop version
uj5u.com熱心網友回復:
當您有細粒度的作業要做時,比如添加兩個整數,并且使用該Parallel.For方法時,您會發現同步開銷以及為每個索引呼叫不可行內lambda 的開銷抵消了由并行化。在這種情況下,通過對一系列索引而不是一次一個索引進行操作來將作業負載分塊是一個好主意。以下是為此目的使用Parallel.ForEach 方法的方法:Partitioner.Create
var left = new int[1_000_000];
var right = new int[1_000_000];
var sum = new int[1_000_000];
var parallelOptions = new ParallelOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount
};
Parallel.ForEach(Partitioner.Create(0, left.Length), parallelOptions, range =>
{
for (int i = range.Item1; i < range.Item2; i )
{
sum[i] = left[i] right[i];
}
});
創建的Partitioner.Create范圍大約是該值的三倍Environment.ProcessorCount,因此在四核機器上,它將總共創建大約 12 個范圍。這是太多范圍(開銷)和太少范圍(不平衡的作業負載)之間的良好折衷。當然,您可以考慮實作自己的磁區方法,并微調每個磁區的大小,而不是使用有些不靈活和過時的Partitioner.Create方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/422759.html
標籤:
上一篇:同時執行一個異步函式
下一篇:從任務內部呼叫靜態方法
