在OpenMP并行代码中赋值tid报错:omp_get_thread_num()使用问题
Fortran OpenMP并行化错误修复方案
错误原因分析
- OpenMP语法违规:
!$OMP PARALLEL DO指令要求紧跟do循环语句,不能在指令和循环之间插入赋值语句(第218行的tid = omp_get_thread_num()),这是编译器报错“unexpected assignment statement”的直接原因。 - 变量属性冲突:
tid被声明为intent(in),这意味着它是只读的输入参数,无法在子例程内部修改赋值,不符合获取线程ID的需求。 - private变量设置错误:循环上限
k被标记为private,会导致每个线程拥有独立的k副本,可能引发循环范围异常,k应该设为shared。
修复后的代码
subroutine costfunction(r,n,k,distancereg,indices,new_centro,cluster,cost,tid) integer, dimension (:), allocatable, intent(out) :: distancereg, indices integer, dimension (:), allocatable, intent(out) :: cluster real, dimension (:,:), allocatable, intent(in) :: r real, dimension (:,:), intent(in), allocatable :: new_centro real, dimension(:), intent(out), allocatable :: cost integer :: i integer, intent(out):: tid ! 修改为intent(out),允许赋值输出 ! 补充声明原代码中未定义的调用变量 real, dimension(:,:), allocatable :: centroid real, dimension(:), allocatable :: distance allocate(cluster(k)) allocate(cost(k)) allocate(distancereg(k)) call min_distance(r,n,k,centroid,distance,indices,distancereg) cluster = 0 !$OMP PARALLEL private(i,tid) shared(cluster,cost,indices,k) tid = omp_get_thread_num() ! 在并行区域内合法获取线程ID !$OMP DO do i=1,k cost(i)=0 cluster(i)=count(indices==i) cost(i)=(1.0/cluster(i))*distancereg(i) print*, "线程ID:", tid, "处理迭代i=", i end do !$OMP END DO !$OMP END PARALLEL print*," total sum of cluster members ",sum(cluster)," vs N ",n end subroutine
关键修复点说明
- 调整OpenMP结构:将
PARALLEL DO拆分为PARALLEL和DO指令,确保在并行区域内、循环前合法获取线程ID。 - 修正变量属性:将
tid的intent(in)改为intent(out),允许子例程对其赋值;同时将tid标记为private,保证每个线程拥有独立的tid副本,避免数据竞争。 - 修正共享/私有变量设置:将
k设为shared,确保所有线程使用相同的循环上限;i设为private,让每个线程处理独立的循环迭代。 - 补充未定义变量:原代码调用
min_distance时用到的centroid和distance未声明,需根据实际需求补充变量声明及内存分配。
内容的提问来源于stack exchange,提问作者Dono Don
相关产品推荐
相关产品推荐

