并行for循环可以写入公共矩阵吗? [英] Can a parallel for loop write to a common matrix?

查看:131
本文介绍了并行for循环可以写入公共矩阵吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定并行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,因为软件可以确定这些迭代不会发生.

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提供的注释中的讨论,以了解为什么这是一个坏主意.那么这种情况呢?

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中的并行循环-概述"的部分(对不起,找不到相应的网页-对于Matlab文档)它描述了循环内所有可能的变量分类,以及parfor循环对每个分类的限制.我在这个答案中讨论的实际上只是冰山一角.例如,由于n是循环变量,因此在parfor循环中诸如n = n + 1的语句也无效,并且不允许对循环变量进行赋值.

I'm not certain what it means for the iterations of a parallel for loop to be independent. Is the following an example of two valid parallel for loops? They write and read the same matrix, but the matrix indices are unique to each iteration.

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

解决方案

As far as parfor is concerned, the following three statements can be regarded as equivalent:

1) The iterations of a parfor loop must be independent.

2) No iteration of a parfor loop may depend on the outcome of any other iteration.

3) The iterations of a parfor loop must be able to be performed in any order (from @Oli)

How do these statements compare to a regular loop? In a typical loop from 1 to 8, the 4th iteration, for example, may depend on iterations 1, 2, and 3, since the software can be certain these iterations have already occurred by the time we reach iteration number 4. It must NOT depend on iterations 5, 6, 7, and 8, since the software can be certain these iterations will not have occurred.

In a parfor loop, as @Oli states, the loops may occur in any order. They may occur in the following order, for example, 7 3 4 1 2 5 8 6. Or any permutation of these 8 numbers. This implies something very important: There is no way of knowing before the fact which iteration will occur first. To see this, just chuck an fprintf('Up to iteration %d of %d\n', t, T) inside your parfor loop, where t is the loop subscript and T is the loop upper bound.

The above statement immediately implies the following conclusion: Since any iteration might occur first, it is critical that no iteration depends on the outcome of any other iteration. I'll conclude the answer with some examples:

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

In this example, (3 * ones(8,1)) clearly does not depend on any other iteration - being constant with respect to the loop counter. Similarly X(:, n) does not depend on any iteration other than the nth. EDIT: I previously was using randn in the above example - see the discussion in comments provided by @AndrewJanke for why this was a bad idea. What about this situation:

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

This is also perfectly valid. Although there is an n + 1 in the expression, this is not the same as depending on iteration number n + 1. Rather it is simply assigning the integer value of the current iteration number, plus 1, to X.

Finally, consider:

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

This would be perfectly valid in a regular loop, since iteration number n-1 will always occur before iteration n (assuming we're looping forwards). But in a parfor loop, this will cause an error, since iteration number n might occur before iteration number n-1. The lingo Matlab uses to describe the problem here is called "slicing". Imagine X to be sliced up by the loop iterations. Then in the nth iteration, you may only ever refer to the nth slice of X.

A final point, if I ever have doubts about a parfor loop, I read the section in the documentation entitled: "Parallel for loops in Matlab - overview" (sorry, can't find the corresponding webpage - unusual for Matlab documentation) It describes all the possible variable classifications inside loops, and the restrictions a parfor loop places on each classification. What I've discussed in this answer is really only the tip of the iceberg. For example, statements such as n = n + 1 are also invalid in a parfor loop, since n is the loop variable, and assignments to the loop variable are not allowed.

这篇关于并行for循环可以写入公共矩阵吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆