当前位置:  开发笔记 > 编程语言 > 正文

并行内存障碍

如何解决《并行内存障碍》经验,为你挑选了2个好方法。

Microsoft的Parallel.For文档包含以下方法:

static void MultiplyMatricesParallel(double[,] matA, double[,] matB, double[,] result)
{
    int matACols = matA.GetLength(1);
    int matBCols = matB.GetLength(1);
    int matARows = matA.GetLength(0);

    // A basic matrix multiplication.
    // Parallelize the outer loop to partition the source array by rows.
    Parallel.For(0, matARows, i =>
    {
        for (int j = 0; j < matBCols; j++)
        {
            double temp = 0;
            for (int k = 0; k < matACols; k++)
            {
                temp += matA[i, k] * matB[k, j];
            }
            result[i, j] = temp;
        }
    }); // Parallel.For
}

在此方法中,可能有多个线程从调用线程读取matAmatB创建并初始化的值,并且可能有多个线程将值写入result,稍后由调用线程读取.在传递给lambda的范围内Parallel.For,数组的读写没有明确的锁定.因为这个例子来自微软,我认为它是线程安全的,但我试图了解幕后发生的事情,使其成为线程安全的.

根据我所阅读的内容以及我在SO上提出的其他问题(例如本文),我需要考虑几个内存障碍才能使这一切顺利进行.那些是:

    调用线程上的内存屏障创建和intializing后matAmatB,

    在每个非调用线程的存储器阻挡从读取值之前matAmatB,

    写入值后,每个非调用线程上的内存屏障result,和

    在读取值之前调用线程上的内存屏障result.

我理解正确吗?

如果是这样,那么Parallel.For以某种方式做到了吗?我去了参考源,但是在编写代码时遇到了麻烦.我没有看到任何lock阻止或MemoryBarrier通话.



1> Patrick Hofm..:

由于数组已经创建,因此写入或读取数组不会导致任何调整大小.此外,代码本身也阻止在数组中读/写相同的位置.

底线是代码总是可以计算在数组中读取和写入的位置,并且这些调用永远不会相互交叉.因此,它是线程安全的.



2> Arch D. Robi..:

您正在寻找的内存障碍位于任务调度程序中.

ParallelFor将工作分解为任务,并且工作窃取调度程序执行这些任务.工作窃取调度程序所需的最小内存障碍是:

    创建任务后的"释放"栏.

    任务被盗时"获取"围栏.

    被盗任务完成时的"释放"围栏.

    正在等待任务的线程的"获取"栅栏.

看看这里的其中1被用来排队任务的原子("联锁")操作暗示.在这里查看任务被盗时原子操作,易失性读取和/或锁定所隐含的2.

我无法追踪3和4的位置.某种原子连接计数器可能暗示了3和4.

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有