代码需要更多时间才能完成超过 1 个线程
Code takes much more time to finish with more than 1 thread
我想用带有临界区的 OpenMP 线程对一些 Fortran 代码进行基准测试。为了模拟真实环境,我尝试在此临界区之前生成一些负载。
!Kompileraufruf: gfortran -fopenmp -o minExample.x minExample.f90
PROGRAM minExample
USE omp_lib
IMPLICIT NONE
INTEGER :: n_chars, real_alloced
INTEGER :: nx,ny,nz,ix,iy,iz, idx
INTEGER :: nthreads, lasteinstellung,i
INTEGER, PARAMETER :: dp = kind(1.0d0)
REAL (KIND = dp) :: j
CHARACTER(LEN=32) :: arg
nx = 2
ny = 2
nz = 2
lasteinstellung= 10000
CALL getarg(1, arg)
READ(arg,*) nthreads
CALL OMP_SET_NUM_THREADS(nthreads)
!$omp parallel
!$omp master
nthreads=omp_get_num_threads()
!$omp end master
!$omp end parallel
WRITE(*,*) "Running OpenMP benchmark on ",nthreads," thread(s)"
n_chars = 0
idx = 0
!$omp parallel do default(none) collapse(3) &
!$omp shared(nx,ny,nz,n_chars) &
!$omp private(ix,iy,iz, idx) &
!$omp private(lasteinstellung,j) !&
DO iz=-nz,nz
DO iy=-ny,ny
DO ix=-nx,nx
! WRITE(*,*) ix,iy,iz
j = 0.0d0
DO i=1,lasteinstellung
j = j + real(i)
END DO
!$omp critical
n_chars = n_chars + 1
idx = n_chars
!$omp end critical
END DO
END DO
END DO
END PROGRAM
我用 gfortran -fopenmp -o test.x test.f90
编译了这段代码并用 time ./test.x THREAD
执行了它
执行这段代码会产生一些奇怪的行为,这取决于线程数(用 OMP_SET_NUM_THREADS 设置):与一个线程(6ms)相比,更多线程的执行花费更多的时间(2 个线程:16000ms,4 个线程:9000ms ) 在我的多核机器上。
什么可能导致这种行为?在某些缓存效果或相关事物中,是否有更好(但仍然简单)的方式来生成负载而无需 运行?
编辑:奇怪的行为:如果我在嵌套循环中写入,2 个线程的执行速度会大大加快。如果将其注释掉,则 2 或 3 个线程的执行将永远进行(写入显示循环变量的增量非常缓慢)......但不是 1 或 4 个线程。我也在另一台多核机器上试过这段代码。那里永远需要 1 个和 3 个线程,但不需要 2 个或 4 个线程。
如果您显示的代码确实完整,那么您在 private
的并行部分中缺少 loadSet
的定义。它是未定义的并且循环
DO i=1,loadSet
j = j + real(i)
END DO
可以进行完全任意次数的迭代。
如果该值之前在代码中的某处定义,您没有显示您可能需要 firstprivate
而不是 private
。
我想用带有临界区的 OpenMP 线程对一些 Fortran 代码进行基准测试。为了模拟真实环境,我尝试在此临界区之前生成一些负载。
!Kompileraufruf: gfortran -fopenmp -o minExample.x minExample.f90
PROGRAM minExample
USE omp_lib
IMPLICIT NONE
INTEGER :: n_chars, real_alloced
INTEGER :: nx,ny,nz,ix,iy,iz, idx
INTEGER :: nthreads, lasteinstellung,i
INTEGER, PARAMETER :: dp = kind(1.0d0)
REAL (KIND = dp) :: j
CHARACTER(LEN=32) :: arg
nx = 2
ny = 2
nz = 2
lasteinstellung= 10000
CALL getarg(1, arg)
READ(arg,*) nthreads
CALL OMP_SET_NUM_THREADS(nthreads)
!$omp parallel
!$omp master
nthreads=omp_get_num_threads()
!$omp end master
!$omp end parallel
WRITE(*,*) "Running OpenMP benchmark on ",nthreads," thread(s)"
n_chars = 0
idx = 0
!$omp parallel do default(none) collapse(3) &
!$omp shared(nx,ny,nz,n_chars) &
!$omp private(ix,iy,iz, idx) &
!$omp private(lasteinstellung,j) !&
DO iz=-nz,nz
DO iy=-ny,ny
DO ix=-nx,nx
! WRITE(*,*) ix,iy,iz
j = 0.0d0
DO i=1,lasteinstellung
j = j + real(i)
END DO
!$omp critical
n_chars = n_chars + 1
idx = n_chars
!$omp end critical
END DO
END DO
END DO
END PROGRAM
我用 gfortran -fopenmp -o test.x test.f90
编译了这段代码并用 time ./test.x THREAD
执行了它
执行这段代码会产生一些奇怪的行为,这取决于线程数(用 OMP_SET_NUM_THREADS 设置):与一个线程(6ms)相比,更多线程的执行花费更多的时间(2 个线程:16000ms,4 个线程:9000ms ) 在我的多核机器上。
什么可能导致这种行为?在某些缓存效果或相关事物中,是否有更好(但仍然简单)的方式来生成负载而无需 运行?
编辑:奇怪的行为:如果我在嵌套循环中写入,2 个线程的执行速度会大大加快。如果将其注释掉,则 2 或 3 个线程的执行将永远进行(写入显示循环变量的增量非常缓慢)......但不是 1 或 4 个线程。我也在另一台多核机器上试过这段代码。那里永远需要 1 个和 3 个线程,但不需要 2 个或 4 个线程。
如果您显示的代码确实完整,那么您在 private
的并行部分中缺少 loadSet
的定义。它是未定义的并且循环
DO i=1,loadSet
j = j + real(i)
END DO
可以进行完全任意次数的迭代。
如果该值之前在代码中的某处定义,您没有显示您可能需要 firstprivate
而不是 private
。