无COLLAPSE子句时,嵌套循环索引使用lastprivate是否合法?
OpenMP嵌套循环索引的private/lastprivate判定与Flang实现建议
针对OpenMP的Flang实现,我们围绕以下程序展开讨论:核心问题是嵌套循环中的ii、iii、iiii等内层循环索引,应被判定为private还是lastprivate?若判定为前者,是否需要将lastprivate子句标记为错误?寻求相关处理建议。
示例程序
module mod integer::i,ii,iii,iiii integer::j,jj,jjj,jjjj integer::k=0 end module program ompv2 use mod !$omp parallel !$omp do reduction(+:k),lastprivate(i,ii,iii,iiii) do i=1,10 do ii=1,10 do iii=1,10 do iiii=1,10 k=k+1 enddo enddo enddo enddo !$omp do reduction(+:k),lastprivate(j,jj,jjj,jjjj) do j=1,10 do jj=1,10 do jjj=1,10 do jjjj=1,10 k=k+1 enddo enddo enddo enddo !$omp do reduction(+:k),lastprivate(m,mm,mmm,mmmm) do m=1,10 do mm=1,10 do mmm=1,10 do mmmm=1,10 k=k+1 enddo enddo enddo enddo !$omp end parallel if (k/=30000) print *,k if (i/=11.or.ii/=11.or.iii/=11.or.iiii/=11) print *,i,ii,iii,iiii if (j/=11.or.jj/=11.or.jjj/=11.or.jjjj/=11) print *,j,jj,jjj,jjjj if (m/=11.or.mm/=11.or.mmm/=11.or.mmmm/=11) print *,m,mm,mmm,mmmm print *,'pass' end
Gfortran的处理结果
% gfortran -fopenmp 0686/0686_0020.f90 0686/0686_0020.f90:12:50: 12 | !$omp do reduction(+:k),lastprivate(i,ii,iii,iiii) | ^ Error: lastprivate variable ‘ii’ is private in outer context 0686/0686_0020.f90:12:50: Error: lastprivate variable ‘iii’ is private in outer context 0686/0686_0020.f90:12:50: Error: lastprivate variable ‘iiii’ is private in outer context ...
分析与处理建议
- OpenMP标准语义:
!$omp do结构仅对最外层循环的索引变量提供默认private属性,且支持通过lastprivate保留循环结束后的最终值;内层循环的索引变量属于外层循环迭代的局部变量,在OpenMP语义中是隐式private,但这种私有性来自外层循环的上下文,不属于当前omp do子句的管控范围。 - Gfortran报错逻辑合理性:
ii、iii、iiii这类内层循环索引,在omp do的上下文里已属于私有变量,不符合lastprivate的使用条件——lastprivate要求变量在并行区域上下文是共享的,或是当前omp do显式声明的私有变量,因此Gfortran的报错是符合标准的。 - Flang实现建议:
- 遵循OpenMP标准,将内层循环索引判定为外层上下文隐式private,而非当前
omp do子句声明的私有变量。 - 当用户在
omp do的lastprivate子句中指定这类内层循环索引时,抛出编译错误,提示类似“变量在外部上下文已为私有”的信息。 - 对于程序中
m、mm这类局部变量,同样执行上述逻辑:仅最外层循环索引m可被lastprivate指定,内层的mm、mmm、mmmm属于外层循环的局部私有变量,禁止出现在lastprivate子句中。
- 遵循OpenMP标准,将内层循环索引判定为外层上下文隐式private,而非当前
内容的提问来源于stack exchange,提问作者rascal2210
相关产品推荐
相关产品推荐

