BENCH_LEGENDRE Subroutine

public subroutine BENCH_LEGENDRE(LMAX, NX, OUTUNIT)

Benchmarks ASSOC_LEGENDRE_NORM_ALL (batch) against looped ASSOC_LEGENDRE (single-mode) calls, for , swept over NX points (one grid sweep per timing, repeated/calibrated per WALL_TIME).

LMAX N_MODES T_BATCH T_LOOP SPEEDUP (seconds per grid-point evaluation).

Arguments

Type IntentOptional Attributes Name
integer(kind=i4), intent(in) :: LMAX

Maximum degree benchmarked, .

integer(kind=i4), intent(in) :: NX

Number of points swept per timing measurement.

integer(kind=i4), intent(in) :: OUTUNIT

Fortran unit number to append one result row to:


Calls

proc~~bench_legendre~~CallsGraph proc~bench_legendre BENCH_LEGENDRE interface~assoc_legendre ASSOC_LEGENDRE proc~bench_legendre->interface~assoc_legendre interface~assoc_legendre_norm_all ASSOC_LEGENDRE_NORM_ALL proc~bench_legendre->interface~assoc_legendre_norm_all proc~wall_time WALL_TIME proc~bench_legendre->proc~wall_time proc~assoc_legendre_dp ASSOC_LEGENDRE_DP interface~assoc_legendre->proc~assoc_legendre_dp proc~assoc_legendre_norm_all_dp ASSOC_LEGENDRE_NORM_ALL_DP interface~assoc_legendre_norm_all->proc~assoc_legendre_norm_all_dp interface~log_fact LOG_FACT proc~assoc_legendre_dp->interface~log_fact proc~plm_index PLM_INDEX proc~assoc_legendre_norm_all_dp->proc~plm_index proc~log_fact_dp LOG_FACT_DP interface~log_fact->proc~log_fact_dp

Called by

proc~~bench_legendre~~CalledByGraph proc~bench_legendre BENCH_LEGENDRE program~bench_main BENCH_MAIN program~bench_main->proc~bench_legendre

Source Code

  SUBROUTINE BENCH_LEGENDRE(LMAX, NX, OUTUNIT)
  IMPLICIT NONE
  INTEGER(KIND=i4), INTENT(IN) :: LMAX
  INTEGER(KIND=i4), INTENT(IN) :: NX
  INTEGER(KIND=i4), INTENT(IN) :: OUTUNIT
  INTEGER(KIND=i4) :: L, M, IX, R, NREP, PSIZE
  REAL(KIND=dp) :: X, DX, T0, T1, T_BATCH, T_LOOP, ACC
  REAL(KIND=dp), ALLOCATABLE :: PNORM(:)

  PSIZE = (LMAX+1)*(LMAX+2)/2
  ALLOCATE(PNORM(PSIZE))
  DX = 1.8_dp / (NX - 1)

  ! ── Batch: one ASSOC_LEGENDRE_NORM_ALL call per grid point ──────────────
  NREP = 1
  DO
    T0 = WALL_TIME()
    DO R = 1, NREP
      DO IX = 0, NX-1
        X = -0.9_dp + IX*DX
        CALL ASSOC_LEGENDRE_NORM_ALL(PNORM, LMAX, X)
      ENDDO
    ENDDO
    T1 = WALL_TIME()
    IF (T1-T0 >= MIN_TIME .OR. NREP >= NREP_CAP) EXIT
    NREP = NREP*2
  ENDDO
  T_BATCH = (T1-T0) / (NREP*NX)
  ACC = SUM(PNORM)
  IF (ACC == -1.0d300) WRITE(*,'(A)') ""  !- defeat dead-code elimination

  ! ── Loop: ASSOC_LEGENDRE called once per (l,m) at each grid point ───────
  ! (skipped above LOOP_LMAX_CAP -- see its declaration for why)
  IF (LMAX <= LOOP_LMAX_CAP) THEN
    NREP = 1
    DO
      ACC = 0.d0
      T0 = WALL_TIME()
      DO R = 1, NREP
        DO IX = 0, NX-1
          X = -0.9_dp + IX*DX
          DO L = 0, LMAX
            DO M = 0, L
              ACC = ACC + ASSOC_LEGENDRE(L, M, X)
            ENDDO
          ENDDO
        ENDDO
      ENDDO
      T1 = WALL_TIME()
      IF (T1-T0 >= MIN_TIME .OR. NREP >= NREP_CAP) EXIT
      NREP = NREP*2
    ENDDO
    T_LOOP = (T1-T0) / (NREP*NX)
    IF (ACC == -1.0d300) WRITE(*,'(A)') ""
  ELSE
    T_LOOP = -1.0_dp   !- sentinel: not measured, see LOOP_LMAX_CAP
  END IF

  IF (T_LOOP >= 0.0_dp) THEN
    WRITE(OUTUNIT,'(I6,1X,I8,1X,ES14.6,1X,ES14.6,1X,F12.3)') &
      LMAX, PSIZE, T_BATCH, T_LOOP, T_LOOP/T_BATCH
  ELSE
    WRITE(OUTUNIT,'(I6,1X,I8,1X,ES14.6,1X,ES14.6,1X,F12.3)') &
      LMAX, PSIZE, T_BATCH, T_LOOP, -1.0_dp
  END IF

  DEALLOCATE(PNORM)
  RETURN
  END SUBROUTINE BENCH_LEGENDRE