【问题标题】:Can a parallel for loop write to a common matrix?并行 for 循环可以写入公共矩阵吗?
【发布时间】:2012-12-07 19:09:27
【问题描述】:

我不确定并行 for 循环的迭代独立意味着什么。以下是两个有效的并行 for 循环的示例吗?它们写入和读取相同的矩阵,但矩阵索引对于每次迭代都是唯一的。

X = zeros(64);
parfor i = 1:64^2
    X(i) = i;
end
parfor i = 1:64
    X(i,:) = X(i,:) .* randn(1,64);
end

【问题讨论】:

  • 如果不是有效的并行循环,Matlab 会输出错误。因此,您只需在 matlab 中运行它,您就会立即得到答案。
  • 文档中的这句话似乎表明 Matlab 并不总是警告:“注意由于迭代顺序的独立性,parfor 的执行不能保证确定性结果。”
  • 这只是意味着可以以任何顺序进行迭代。这对您的案件没有影响。
  • 这就是我想知道的! “有效的并行循环”是指“按预期运行”。
  • 实际上我认为它确实对这种特殊情况有影响 - randn 取决于全局 rng 状态,因此其结果将取决于循环通过的位置和运行顺序。 (我不知道rng 状态是从父级传递给工人,还是它们都从默认种子开始;无论哪种方式,都有交互。)听起来像是他们警告的那种不确定的结果。 parfor 正确性检查可能看不到这一点,因为它影响的是隐藏的全局状态,而不是工作区中的切片变量或对象。

标签: matlab parallel-processing


【解决方案1】:

parfor而言,以下三个语句可以认为是等价的:

1) parfor 循环的迭代必须是独立的。

2) parfor 循环的任何迭代都可能依赖于任何其他迭代的结果。

3) parfor 循环的迭代必须能够以任何顺序执行(来自@Oli)

这些语句与常规循环相比如何?例如,在从 1 到 8 的典型循环中,第 4 次迭代可能取决于迭代 1、2 和 3,因为软件可以确定这些迭代在我们到达第 4 次迭代时已经发生。它不能取决于迭代 5、6、7 和 8,因为软件可以确定这些迭代不会发生。

parfor 循环中,正如@Oli 所述,循环可以以任何顺序发生。它们可能按以下顺序出现,例如,7 3 4 1 2 5 8 6。或者这 8 个数字的任何排列。这意味着一些非常重要的事情:没有办法知道哪个迭代将首先发生。 要看到这一点,只需在 parfor 循环中插入一个 fprintf('Up to iteration %d of %d\n', t, T),其中 t 是循环下标和T 是循环上限。

上述陈述直接暗示了以下结论:由于任何迭代都可能首先发生,因此任何迭代都取决于任何其他迭代的结果,这一点至关重要。我将用一些例子来结束答案:

X = ones(8, 8)
parfor n = 1:8
    X(:,n) = X(:,n) .* (3 * ones(8,1));
end

在这个例子中,(3 * ones(8,1)) 显然不依赖于任何其他迭代——相对于循环计数器是恒定的。同样,X(:, n) 不依赖于除第 n 次以外的任何迭代。 编辑:我之前在上面的示例中使用了randn - 请参阅@AndrewJanke 提供的 cmets 中的讨论,了解为什么这是一个坏主意。这种情况怎么办:

X = ones(8, 8);
parfor n = 1:8
    X(:,n) = X(:,n) + (n + 1);
end

这也是完全有效的。虽然表达式中有n + 1,但这与依赖迭代次数n + 1不同。相反,它只是将当前迭代次数的整数值加上 1 分配给X

最后,考虑一下:

X = ones(8, 1);
parfor n = 2:8
    X(n, 1) = X(n-1, 1) + 1;
end

这在常规循环中是完全有效的,因为迭代号 n-1 将始终出现在迭代 n 之前(假设我们正在向前循环)。但在parfor 循环中,这将导致错误,因为迭代编号n 可能出现在迭代编号n-1 之前。 Matlab 用来描述这里问题的术语称为“切片”。想象X 被循环迭代分割。然后在第 n 次迭代中,您可能只会引用 X 的第 n 个切片。

最后一点,如果我对 parfor 循环有疑问,我阅读了文档中标题为“Matlab 中的并行 for 循环 - 概述”的部分(抱歉,找不到相应的网页 - 对于Matlab 文档)它描述了循环内所有可能的变量分类,以及parfor 循环对每个分类的限制。我在这个答案中讨论的实际上只是冰山一角。例如,n = n + 1 等语句在parfor 循环中也是无效的,因为n 是循环变量,不允许对循环变量赋值。

【讨论】:

  • 嗯。你知道,randn 可能是一个不好的例子,因为它对 Matlab 的全局状态有副作用。这是一个 PRNG,每个 Matlab 会话都以相同的随机种子开始;每个randn 呼叫都会推进它。所以它的输出确实取决于之前的循环迭代; randn 的输出是该会话中调用它的次数的函数。每个工作人员都是一个会话,因此此代码的结果将直接取决于有多少工作人员、循环运行的顺序以及影响这些会话的rng 状态的其他因素。
  • 也就是说,我认为使用randn 违反了“重要的是,没有迭代取决于任何其他迭代的结果”规则,因为调用randn 的迭代结果的一部分是rng 是高级的,那是randn 的隐藏输入。这是parfor 检查无法捕获的不确定性,因此人类程序员需要避免或确保不确定性“无关紧要”。这里要做的“正确”事情可能是在parfor之前生成整个rands块,然后在循环迭代中对其进行切片;那么您将具有可重复性。
  • @AndrewJanke 我没想到!非常聪明!我已经相应地调整了答案以删除randn。我认为将大多数随机数生成器的固有确定性的讨论纳入上述答案只会让读者感到困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 2019-09-08
相关资源
最近更新 更多