gpt4 book ai didi

C# 并行与。线程代码性能

转载 作者:可可西里 更新时间:2023-11-01 09:12:12 24 4
gpt4 key购买 nike

我一直在测试 System.Threading.Parallel 与 Threading 的性能,我很惊讶地发现 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();
}
}
}

程序如下:

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();

更新:

考虑到锁定:我尝试了以下代码片段。同样的结果,Parallel 似乎完成得慢得多。

路径=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();
}

更新 2:只是快速更新我的机器有四核处理器。所以 Parallel 有 4 个内核可用。

最佳答案

引用 blog post作者:Reed Copsey Jr:

Parallel.ForEach is a bit more complicated, however. When working with a generic IEnumerable, the number of items required for processing is not known in advance, and must be discovered at runtime. In addition, since we don’t have direct access to each element, the scheduler must enumerate the collection to process it. Since IEnumerable is not thread safe, it must lock on elements as it enumerates, create temporary collections for each chunk to process, and schedule this out.

锁定和复制可能会使 Parallel.ForEach 花费更长的时间。此外,分区和 ForEach 的调度程序可能会影响并产生开销。我测试了你的代码并增加了每个任务的 sleep ,然后结果更接近,但 ForEach 仍然更慢。

[编辑 - 更多研究]

我在执行循环中添加了以下内容:

if (Thread.CurrentThread.ManagedThreadId > maxThreadId)
maxThreadId = Thread.CurrentThread.ManagedThreadId;

这在我的机器上显示的是,与具有当前设置的另一个相比,ForEach 使用的线程少了 10 个。如果您想从 ForEach 中获得更多线程,则必须摆弄 ParallelOptions 和调度程序。

参见 Does Parallel.ForEach limits the number of active threads?

关于C# 并行与。线程代码性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3572554/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com