首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用嵌套Parallel.For

使用嵌套Parallel.For
EN

Stack Overflow用户
提问于 2010-07-19 11:39:34
回答 3查看 7.9K关注 0票数 7

考虑一下这个例子:

代码语言:javascript
复制
var x = 0;

for (var i = 0; i < 100; i++ )
{
    for (var a = i+1; a < 100; a++)
        x += 1;
}

当打印x时,我们总是得到4950。如果我想并行化呢?

这就是我想出来的

代码语言:javascript
复制
Parallel.For(0, 100, i => Parallel.For(i + 1, 100, a => { x += 1; }));

但是,,这并不是每次运行它时都打印4950。为什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-19 11:48:26

并行扩展帮助您以近乎命令式的语法创建、分配、运行和集合任务.没有做的是照顾每种类型的线程安全(陷阱之一)。您正在尝试使并行线程同时更新单个共享变量。要正确地执行这样的操作,您必须引入例如锁定。

我不知道你想做什么。我假设您的代码只是一个占位符或实验。只有当您能够隔离不同的工作片段时,并行化才适合;而不是当您必须经常与共享数据会合时。

票数 16
EN

Stack Overflow用户

发布于 2013-10-04 18:07:19

这是一种“正确”的方法,它不需要锁定最终的总计对象,只需要在每个本地线程的循环结束时执行互锁操作。

代码语言:javascript
复制
int x = 0;
Parallel.For(0, 100,
    () => 0, //LocalInit
    (i, loopstate, outerlocal) =>
    {
        Parallel.For(i + 1, 100,
            () => 0, //LocalInit
            (a, loopState, innerLocal) => { return innerLocal + 1; },
            (innerLocal) => Interlocked.Add(ref outerlocal, innerLocal)); //Local Final
        return outerlocal;
    },
    (outerLocal) => Interlocked.Add(ref x, outerLocal)); //Local Final

然而,让两个嵌套的Parallel语句来完成这一点工作可能是个坏主意。有一个开销成本需要考虑,如果您正在做这么少的工作,最好只做一个Parallel语句,或者根本没有。

我强烈建议您下载并阅读并行编程模式,它详细介绍了为什么像这样的小型嵌套并行循环不是一个好主意。

票数 2
EN

Stack Overflow用户

发布于 2010-07-19 12:12:31

作为每次锁定的替代方法,您可以结合使用线程局部变量和锁:

代码语言:javascript
复制
Object thisLock = new Object();
var globalSum = 0;
System.Threading.Tasks.Parallel.For(0, 100, i => {
    System.Threading.Tasks.Parallel.For(i + 1, 100, () => 0, (num, loopState, subSum) => ++subSum, subSum => { 
        lock(thisLock) { globalSum += subSum; }
    });
});

Console.WriteLine(globalSum);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3280688

复制
相关文章

相似问题

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