ace*_*ace 10 c# parallel-processing pfx
我一直在测试System.Threading.Parallel和线程的性能,我很惊讶看到Parallel需要更长时间来完成任务而不是线程.我确定这是因为我对Parallel的了解有限,我刚刚开始阅读.
我以为我会分享几个片段,如果有人能指出我,并行代码运行速度慢于线程代码.还试图运行相同的比较来查找素数,并发现并行代码比线程代码更晚完成.
public class ThreadFactory
{
int workersCount;
private List<Thread> threads = new List<Thread>();
public ThreadFactory(int threadCount, int workCount, Action<int, int, string> action)
{
workersCount = threadCount;
int totalWorkLoad = workCount;
int workLoad = totalWorkLoad / workersCount;
int extraLoad = totalWorkLoad % workersCount;
for (int i = 0; i < workersCount; i++)
{
int min, max;
if (i < (workersCount - 1))
{
min = (i * workLoad);
max = ((i * workLoad) + workLoad - 1);
}
else
{
min = (i * workLoad);
max = (i * workLoad) + (workLoad - 1 + extraLoad);
}
string name = "Working Thread#" + i;
Thread worker = new Thread(() => { action(min, max, name); });
worker.Name = name;
threads.Add(worker);
}
}
public void StartWorking()
{
foreach (Thread thread in threads)
{
thread.Start();
}
foreach (Thread thread in threads)
{
thread.Join();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是程序:
Stopwatch watch = new Stopwatch();
watch.Start();
int path = 1;
List<int> numbers = new List<int>(Enumerable.Range(0, 10000));
if (path == 1)
{
Parallel.ForEach(numbers, x =>
{
Console.WriteLine(x);
Thread.Sleep(1);
});
}
else
{
ThreadFactory workers = new ThreadFactory(10, numbers.Count, (min, max, text) => {
for (int i = min; i <= max; i++)
{
Console.WriteLine(numbers[i]);
Thread.Sleep(1);
}
});
workers.StartWorking();
}
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
更新:
考虑锁定:我尝试了下面的代码片段.同样的结果,Parallel似乎完成得慢得多.
path = 1; cieling = 10000000;
List<int> numbers = new List<int>();
if (path == 1)
{
Parallel.For(0, cieling, x =>
{
lock (numbers)
{
numbers.Add(x);
}
});
}
else
{
ThreadFactory workers = new ThreadFactory(10, cieling, (min, max, text) =>
{
for (int i = min; i <= max; i++)
{
lock (numbers)
{
numbers.Add(i);
}
}
});
workers.StartWorking();
}
Run Code Online (Sandbox Code Playgroud)
更新2: 只需快速更新我的机器有四核处理器.所以Parallel有4个核心可用.
参考Reed Copsey Jr 的博客文章:
\n\n\n\n\n然而,Parallel.ForEach 有点复杂。使用通用 IEnumerable 时,处理所需的项目数量事先未知,必须在运行时发现。此外,由于我们无法直接访问每个元素,因此调度程序必须枚举集合来处理它。 由于 IEnumerable 不是线程安全的,因此它必须在枚举时锁定元素,为每个要处理的块创建临时集合,并将其调度出去。
\n
锁定和复制可能会使 Parallel.ForEach 花费更长的时间。ForEach 的分区和调度程序也会影响并产生开销。我测试了你的代码并增加了每个任务的睡眠时间,然后结果更接近,但 ForEach 仍然较慢。
\n\n[编辑-更多研究]
\n\n我将以下内容添加到执行循环中:
\n\nif (Thread.CurrentThread.ManagedThreadId > maxThreadId)\n maxThreadId = Thread.CurrentThread.ManagedThreadId;\nRun Code Online (Sandbox Code Playgroud)\n\n这在我的机器上显示的是,与当前设置的另一台机器相比,ForEach 减少了 10 个线程的使用。如果您想从 ForEach 中获得更多线程,则必须摆弄 ParallelOptions 和 Scheduler。
\n\n请参阅Parallel.ForEach 是否限制活动线程数?
\n