C#Parallel Vs. 线程代码性能

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个核心可用.

Mik*_*son 4

参考Reed Copsey Jr 的博客文章:

\n\n
\n

然而,Parallel.ForEach 有点复杂。使用通用 IEnumerable 时,处理所需的项目数量事先未知,必须在运行时发现。此外,由于我们无法直接访问每个元素,因此调度程序必须枚举集合来处理它。 由于 IEnumerable 不是线程安全的,因此它必须在枚举时锁定元素,为每个要处理的块创建临时集合,并将其调度出去

\n
\n\n

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

\n\n

[编辑-更多研究]

\n\n

我将以下内容添加到执行循环中:

\n\n
if (Thread.CurrentThread.ManagedThreadId > maxThreadId)\n   maxThreadId = Thread.CurrentThread.ManagedThreadId;\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

请参阅Parallel.ForEach 是否限制活动线程数?

\n