首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Parallel.For性能

Parallel.For性能
EN

Stack Overflow用户
提问于 2013-08-13 07:45:46
回答 1查看 1.7K关注 0票数 2

这段代码来自微软的文章http://msdn.microsoft.com/en-us/library/dd460703.aspx,有一些小改动:

代码语言:javascript
复制
        const int size = 10000000;
        int[] nums = new int[size];
        Parallel.For(0, size, i => {nums[i] = 1;});
        long total = 0;

        Parallel.For<long>(
            0, size, () => 0,
            (j, loop, subtotal) =>
            {
                return subtotal + nums[j];
            },
            (x) => Interlocked.Add(ref total, x) 
        );

        if (total != size)
        {
            Console.WriteLine("Error");
        }

非并行循环版本是:

代码语言:javascript
复制
        for (int i = 0; i < size; ++i)
        {
            total += nums[i];
        }

当我使用StopWatch类测量循环执行时间时,我看到并行版本比以前慢了10-20%。测试是在Windows 7 64位,Intel i5-2400 CPU,4核,4 GB RAM上进行的.当然,在发布配置中。

在我的实际程序中,我试图计算一个图像直方图,并行版本运行速度要慢10倍。当每次循环调用都非常快时,这样的计算任务能否成功地与TPL并行?

编辑

最后,当我将整个图像分割成一定数量的块时,我成功地用Parallel.For减少了50%的直方图计算执行时间。现在,每个循环体调用都处理整个块,而不是一个像素。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-13 07:56:46

因为Parallel.For应该被用来处理一些杂乱无章的事情,而不是简单的数字之和!仅仅使用委托(j, loop, subtotal) =>可能就足以给出10%-20%的时间。我们甚至都没说到线程的开销。在for循环中看到一些针对委托夏季的基准,不仅看到“真实世界”时间,而且看到CPU时间,这将是很有趣的。

我甚至添加了一个与Parallel.For<>委托相同的“简单”委托的比较。

嗯..。现在我有一些32位的数字,在我的个人电脑上(一个AMD六核)

代码语言:javascript
复制
32 bits
Parallel: Ticks:      74581, Total ProcessTime:    2496016
Base    : Ticks:      90395, Total ProcessTime:     312002
Func    : Ticks:     147037, Total ProcessTime:     468003

并行在墙时间稍微快一点,但在处理器时慢8倍:)

但在64比特:

代码语言:javascript
复制
64 bits
Parallel: Ticks:     104326, Total ProcessTime:    2652017
Base    : Ticks:      51664, Total ProcessTime:     156001
Func    : Ticks:      77861, Total ProcessTime:     312002

修改后的代码:

代码语言:javascript
复制
Console.WriteLine("{0} bits", IntPtr.Size == 4 ? 32 : 64);

var cp = Process.GetCurrentProcess();
cp.PriorityClass = ProcessPriorityClass.High;

const int size = 10000000;
int[] nums = new int[size];
Parallel.For(0, size, i => { nums[i] = 1; });

GC.Collect();
GC.WaitForPendingFinalizers();

long total = 0;

{
    TimeSpan start = cp.TotalProcessorTime;
    Stopwatch sw = Stopwatch.StartNew();

    Parallel.For<long>(
        0, size, () => 0,
        (j, loop, subtotal) =>
        {
            return subtotal + nums[j];
        },
        (x) => Interlocked.Add(ref total, x)
    );

    sw.Stop();
    TimeSpan end = cp.TotalProcessorTime;

    Console.WriteLine("Parallel: Ticks: {0,10}, Total ProcessTime: {1,10}", sw.ElapsedTicks, (end - start).Ticks);
}

if (total != size)
{
    Console.WriteLine("Error");
}

GC.Collect();
GC.WaitForPendingFinalizers();

total = 0;

{
    TimeSpan start = cp.TotalProcessorTime;
    Stopwatch sw = Stopwatch.StartNew();

    for (int i = 0; i < size; ++i)
    {
        total += nums[i];
    }

    sw.Stop();
    TimeSpan end = cp.TotalProcessorTime;

    Console.WriteLine("Base    : Ticks: {0,10}, Total ProcessTime: {1,10}", sw.ElapsedTicks, (end - start).Ticks);
}

if (total != size)
{
    Console.WriteLine("Error");
}

GC.Collect();
GC.WaitForPendingFinalizers();

total = 0;

Func<int, int, long, long> adder = (j, loop, subtotal) =>
{
    return subtotal + nums[j];
};

{
    TimeSpan start = cp.TotalProcessorTime;
    Stopwatch sw = Stopwatch.StartNew();

    for (int i = 0; i < size; ++i)
    {
        total = adder(i, 0, total);
    }

    sw.Stop();
    TimeSpan end = cp.TotalProcessorTime;

    Console.WriteLine("Func    : Ticks: {0,10}, Total ProcessTime: {1,10}", sw.ElapsedTicks, (end - start).Ticks);
}

if (total != size)
{
    Console.WriteLine("Error");
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18203388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档