【问题标题】:Why I am getting segmentation fault in Openmp when adding numbers stored in an array?为什么在添加存储在数组中的数字时在 Openmp 中出现分段错误?
【发布时间】:2026-01-21 19:45:01
【问题描述】:

我是 Openmp 的新手。我正在总结存储在数组中的 N 个整数并使用 gfortran 编译代码。直到 N=10^6,串行和并行代码得到的结果是完全一样的。对于 N=10^7,串行代码正在运行,但并行代码(使用 -fopenmp 标志编译后)给出“分段错误”。我在这里给出了我的代码。谁能帮助我为什么会这样?

  use omp_lib
  REAL*8 r,summ,sl
  parameter (N=10000000)
  dimension r(N)

  do i=1,N
  r(i)=i
  enddo

  summ=0.0d00
  sl=0.0d00

  !$OMP PARALLEL FIRSTPRIVATE(sl) SHARED(r,summ)
  !$OMP DO 
  do i=1,N
  sl=sl+r(i)
  enddo
  !$OMP END DO
  !$OMP CRITICAL
  summ=summ+sl
  !$OMP END CRITICAL
  !$OMP END PARALLEL

  write(*,*)'SUM',summ

  end

【问题讨论】:

  • 欢迎,请使用tour 并使用标签fortran 解决Fortran 问题。
  • 请看链接,错误是一样的,必须使用shared,而不是firstprivate。实际上,您应该完全删除 sl 并使用 summ 进行缩减。
  • 但是Segfault的真正原因在这里*.com/questions/13264274/…我建议使用可分配数组,但你也可以使用无限堆栈。
  • 我认为firstprivateshared 没有任何问题。累加是通过初始化为零的线程局部变量完成的,然后每个线程将其私有累加器原子地求和到(共享)全局累加器中。这与其他问题(未共享全局累加器)不同。

标签: parallel-processing fortran openmp gfortran


【解决方案1】:

我以前也遇到过同样的问题。问题是您的代码似乎需要大内存。

确保在编译代码-mcmodel=medium 时使用编译器选项。此外,当您使用-fopenmp 时,您的编译器会系统地调用-frecursive,这会将您的堆栈大小限制为默认值。因此,您的代码尝试在导致分段错误的堆栈限制之外写入。要摆脱这个问题,您必须取消堆栈的默认限制。一种快速执行此操作的方法是在终端上运行命令ulimit -s unlimited,然后在同一终端中启动您的代码。您还可以使用编译选项 -fmax-stack-var-size=n 和 n 的良好值来设置堆栈的大小,使其适合您的数据。

另外,我建议使用reduction (+:sum) 子句来计算总和,而不是声明在这种情况下无效且可避免的临界区域。

我希望这对您有所帮助。

【讨论】:

    最近更新 更多