在更好的优化标志和 OpenMP 之后,向量的计算变得更慢

Calculations on vectors become slower after better optimization flag and OpenMP

考虑以下 Fort运行 代码

program example
    implicit none
    integer, parameter  ::  ik = selected_int_kind(15)
    integer, parameter  ::  rk = selected_real_kind(15,307)

    integer(ik)         :: N, i, j, pc, time_rate, start_time, end_time, M

    real(rk), allocatable:: K(:,:), desc(:,:)
    real(rk)                :: kij, dij

    integer             :: omp_get_num_threads, nth
    N = 2000
    M = 400

    allocate(K(N,N))
    allocate(desc(N,M))

    pc=10
    do i = 1, N
        desc(i,:) = real(i,rk)
        if (i==int(N*pc)/100) then
            print * ,"desc % complete: ",pc
            pc=pc+10
        endif
    enddo
    call system_clock(start_time)
    !$OMP PARALLEL PRIVATE(nth)
    nth = omp_get_num_threads()
    print *,"omp threads", nth
    !$OMP END PARALLEL

    !$OMP PARALLEL DO &
    !$OMP DEFAULT(SHARED) &
    !$OMP PRIVATE(i,j,dij,kij)
    do i = 1, N
        do j = i, N
            dij = sum(abs(desc(i,:) - desc(j,:)))
            kij = dexp(-dij)
            K(i,j) = kij
            K(j,i) = kij
        enddo
        K(i,i) = K(i,i) + 0.1
    enddo
    !$OMP END PARALLEL DO

    call system_clock(end_time, time_rate)
    print* , "Time taken for Matrix:", real(end_time - start_time, rk)/real(time_rate, rk)

end program example

我在 MacOS X 10.11 上使用 gfort运行-6 使用以下标志编译它

  1. gfortran example.f90 -fopenmp -O0
  2. gfortran example.f90 -fopenmp -O3
  3. gfortran example.f90 -fopenmp -mtune=native

接下来我 运行 它使用 OMP_NUM_THREADS 变量的单线程和双线程。我可以看到它正在使用两个核心。然而,应该启用矢量化的 O3 标志对性能没有任何帮助,如果有的话,它会稍微降低性能。时间如下(以秒为单位)(平均超过 10 次运行):

|Thrds->|   1  |  2  |
|Opt    |      |     |
----------------------
|O0     |10.962|9.183|
|O3     |11.581|9.250|
|mtune  |11.211|9.084|

我的程序有什么问题?

首先,如果你想从-O3获得好的性能,你应该给它一些实际上可以优化的东西。大部分工作发生在 sum 内在函数中,它作用于向量化表达式。当您从 -O0 切换到 -O3.

时,它不会得到任何优化

此外,如果您想要更好的性能,请转置 desc,因为 desc(i,:) 在内存中是不连续的。 desc(:,i) 是。那是 Fortran - 它的矩阵是列优先的。