我不确定并行 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
我不确定并行 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
就parfor
目前而言,以下三种说法可以认为是等价的:
1)循环的迭代parfor
必须是独立的。
2)循环的任何迭代都parfor
可能取决于任何其他迭代的结果。
3)循环的迭代parfor
必须能够以任何顺序执行(来自@Oli)
这些语句与常规循环相比如何?例如,在从 1 到 8 的典型循环中,第 4 次迭代可能取决于迭代 1、2 和 3,因为软件可以确定这些迭代在我们到达第 4 次迭代时已经发生。它不能取决于迭代 5、6、7 和 8,因为软件可以确定这些迭代不会发生。
正如@Oli 所说,在parfor
循环中,循环可能以任何顺序发生。它们可能按以下顺序出现,例如,7 3 4 1 2 5 8 6。或者这 8 个数字的任何排列。这意味着一些非常重要的事情:没有办法知道哪个迭代将首先发生。要看到这一点,只需fprintf('Up to iteration %d of %d\n', t, T)
在循环中插入一个,循环下标parfor
在哪里,循环上限在哪里。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 提供的评论中的讨论,了解为什么这是一个坏主意。这种情况怎么办:
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
.
最后一点,如果我对parfor
循环有疑问,我阅读了文档中题为“Matlab 中的并行 for 循环 - 概述”的部分(抱歉,找不到相应的网页 - 对于 Matlab 文档来说不常见)它描述了所有循环内可能的变量分类,以及parfor
循环对每个分类的限制。我在这个答案中讨论的实际上只是冰山一角。例如,诸如语句在循环n = n + 1
中也是无效的parfor
,因为n
是循环变量,并且不允许对循环变量进行赋值。