我正在阅读有关循环变换技术的内容,我很难理解循环偏移如何使循环可并行化这里有两个循环,初始循环和第二个循环,两者之间有什么区别?它们中的两个取决于i和j上的前一次迭代,是什么使得第二个循环可以进行?或者为什么我们可以在第二个而不是第一个进行交换?它们都依赖于i和j
for(int i =2; i < 5; i++){
for(int j =2; j < 5; j++){
A[i][j] = A[i-1][j] + A[i][j-1];
}
}
for(int i =2; i < 5; i++){
for(int j =2+i; j < 5+i; j++){
A[i][j-i] = A[i-1][j-i] + A[i][j-1-i];
}
}
答案 0 :(得分:3)
我对此没有任何赞誉,我只是为您格式化并从其他来源复制了它,我希望它可以帮助您
[来源:ECE 1754, Survey of Loop Transformation Techniques, Eric LaForest, March 19, 2010]
所有关于两个执行迭代之间的距离,在第一个外部循环和内部循环之间的距离是1,因此它们之间存在依赖关系。
循环偏移正如它所说的那样:它会扭曲内循环的执行 相对于外部的。如果内部循环依赖外部循环阻止它并行运行,这将非常有用。例如,以下代码具有{(1,0,),(0,1)}的依赖向量。两个循环都可以并行化 因为他们每个人都有依赖。简单地交换循环仅仅是 交换持有依赖关系的索引,什么都不做。
do i = 2, n-1
do j = 2, m-1
a[i,j] =
(a[a-1,j] + a[i,j-1] + a[i+1,j] + a[i,j+1]) / 4
end do
end do
循环偏移是通过添加外部循环的索引来实现的 偏移因子f,到内环的边界并减去相同的值 来自内循环索引的所有用途。减法使索引保持在 新的循环边界,保持程序的正确性。对...的影响 内循环迭代是通过 f 相对向前移动它们在数组中的位置 到当前外部循环,增加到外部循环的依赖性距离 以相同的方式。换句话说,给定依赖向量(a,b),倾斜 将其转换为(a,f a + b)。由于这种转变保留了词典 依赖的顺序,它总是合法的。将偏斜因子应用于1 上面的内部循环产生以下代码:
do i = 2, n-1
do j = 2+i, m-1+i
a[i,j-i] =
(a[a-1,j-i] + a[i,j-1-i] + a[i+1,j-i] + a[i,j+1-i]) / 4
end do
end do
这个新代码以相同的方式执行,但具有{(1,1),(0,1)}的依赖关系。两个循环仍然具有依赖性。但是,此时交换循环会产生依赖向量{(1,0),(1,1)},如下面的代码所示:
do j = 4, m+n-2
do i = max(2, j-m+1), min(n-1, j-2)
a[i,j-i] =
(a[a-1,j-i] + a[i,j-1-i] + a[i+1,j-i] + a[i,j+1-i]) / 4
end do
end do
内部循环现在可以并行化,因为它现在没有对j的循环携带依赖性,并且对i的依赖性由外部循环承载。注意 交换偏斜的循环边界不再简单:每个循环必须 考虑另一个循环的上限和下限。