From 1c8ca7e287b301ab1b497e94ca0b16ef751eba7d Mon Sep 17 00:00:00 2001 From: Bill Ladwig Date: Fri, 1 Dec 2017 16:13:19 -0700 Subject: [PATCH] Added OpenMP runtime library wrappers and build scripts --- build_scripts/gnu_no_omp.sh | 8 + build_scripts/gnu_omp.sh | 9 + fortran/omp.f90 | 667 ++++++++++++++++++++++++++++++++++++ fortran/ompgen.F90 | 94 ++--- fortran/rip_cape.f90 | 1 - fortran/wrffortran.pyf | 155 +++++++++ setup.py | 1 + src/wrf/api.py | 36 +- src/wrf/constants.py | 9 +- src/wrf/extension.py | 149 +++++++- 10 files changed, 1084 insertions(+), 45 deletions(-) create mode 100755 build_scripts/gnu_no_omp.sh create mode 100755 build_scripts/gnu_omp.sh create mode 100644 fortran/omp.f90 diff --git a/build_scripts/gnu_no_omp.sh b/build_scripts/gnu_no_omp.sh new file mode 100755 index 0000000..6f73784 --- /dev/null +++ b/build_scripts/gnu_no_omp.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +cd ../fortran +gfortran -E ompgen.F90 -cpp -o omp.f90 +f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature +cd .. +python setup.py clean --all +python setup.py config_fc --f90flags="-mtune=generic" build_ext build diff --git a/build_scripts/gnu_omp.sh b/build_scripts/gnu_omp.sh new file mode 100755 index 0000000..cf66f27 --- /dev/null +++ b/build_scripts/gnu_omp.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +cd ../fortran +gfortran -E ompgen.F90 -fopenmp -cpp -o omp.f90 +f2py *.f90 -m _wrffortran -h wrffortran.pyf --overwrite-signature --no-wrap-functions +cd .. +python setup.py clean --all +python setup.py config_fc --f90flags="-mtune=generic -fopenmp" build_ext --libraries="gomp" build + diff --git a/fortran/omp.f90 b/fortran/omp.f90 new file mode 100644 index 0000000..3da26d4 --- /dev/null +++ b/fortran/omp.f90 @@ -0,0 +1,667 @@ +# 1 "ompgen.F90" +# 1 "" +# 1 "" +# 1 "ompgen.F90" +MODULE omp_constants +# 52 "ompgen.F90" + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 4 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 8 + INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_static = 1 + INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_dynamic = 2 + INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_guided = 3 + INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_auto = 4 + + +END MODULE omp_constants + + +SUBROUTINE fomp_set_num_threads(num_threads) + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER, INTENT(IN) :: num_threads + + + + + +END SUBROUTINE fomp_set_num_threads + + +FUNCTION fomp_get_num_threads() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_num_threads + + + + + fomp_get_num_threads = -1 + + +END FUNCTION fomp_get_num_threads + + +FUNCTION fomp_get_max_threads() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_max_threads + + + + + fomp_get_max_threads = -1 + + +END FUNCTION fomp_get_max_threads + + +FUNCTION fomp_get_thread_num() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_thread_num + + + + + fomp_get_thread_num = -1 + + +END FUNCTION fomp_get_thread_num + + +FUNCTION fomp_get_num_procs() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_num_procs + + + + + fomp_get_num_procs = -1 + + +END FUNCTION fomp_get_num_procs + + +FUNCTION fomp_in_parallel() + + + + + IMPLICIT NONE + + !f2py threadsafe + + LOGICAL :: fomp_in_parallel + + + + + fomp_in_parallel = .FALSE. + + +END FUNCTION fomp_in_parallel + + +SUBROUTINE fomp_set_dynamic(dynamic_threads) + + + + + IMPLICIT NONE + + !f2py threadsafe + + LOGICAL, INTENT(IN) :: dynamic_threads + + + + + +END SUBROUTINE fomp_set_dynamic + + +FUNCTION fomp_get_dynamic() + + + + + IMPLICIT NONE + + !f2py threadsafe + + LOGICAL :: fomp_get_dynamic + + + + + fomp_get_dynamic = .FALSE. + + +END FUNCTION fomp_get_dynamic + + +SUBROUTINE fomp_set_nested(nested) + + + + + IMPLICIT NONE + + !f2py threadsafe + + LOGICAL, INTENT(IN) :: nested + + + + + +END SUBROUTINE fomp_set_nested + + +FUNCTION fomp_get_nested() + + + + + IMPLICIT NONE + + !f2py threadsafe + + LOGICAL :: fomp_get_nested + + + + + fomp_get_nested = .FALSE. + + +END FUNCTION fomp_get_nested + + +SUBROUTINE fomp_set_schedule(kind, modifier) + + + + USE omp_constants, ONLY : fomp_sched_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_sched_kind), INTENT(IN) :: kind + INTEGER, INTENT(IN) :: modifier + + + + + +END SUBROUTINE fomp_set_schedule + + +SUBROUTINE fomp_get_schedule(kind, modifier) + + + + USE omp_constants, ONLY : fomp_sched_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_sched_kind), INTENT(OUT) :: kind + INTEGER, INTENT(OUT) :: modifier + + + + + kind = -1 + modifier = -1 + + +END SUBROUTINE fomp_get_schedule + + +FUNCTION fomp_get_thread_limit() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_thread_limit + + + + + fomp_get_thread_limit = -1 + + +END FUNCTION fomp_get_thread_limit + + +SUBROUTINE fomp_set_max_active_levels(max_levels) + + + + + IMPLICIT NONE + + !f2py threadsafe + + + + + INTEGER, INTENT(IN) :: max_levels + + + + + + +END SUBROUTINE fomp_set_max_active_levels + + +FUNCTION fomp_get_max_active_levels() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_max_active_levels + + + + + fomp_get_max_active_levels = -1 + + +END FUNCTION fomp_get_max_active_levels + + +FUNCTION fomp_get_level() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_level + + + + + fomp_get_level = -1 + + +END FUNCTION fomp_get_level + + +FUNCTION fomp_get_ancestor_thread_num(level) + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER, INTENT(IN) :: level + INTEGER :: fomp_get_ancestor_thread_num + + + + + fomp_get_ancestor_thread_num = -1 + + +END FUNCTION fomp_get_ancestor_thread_num + + +FUNCTION fomp_get_team_size(level) + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER, INTENT(IN) :: level + INTEGER :: fomp_get_team_size + + + + + fomp_get_team_size = -1 + + +END FUNCTION fomp_get_team_size + + +FUNCTION fomp_get_active_level() + + + + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER :: fomp_get_active_level + + + + + fomp_get_active_level = -1 + + +END FUNCTION fomp_get_active_level + + +FUNCTION fomp_in_final() + + + + + IMPLICIT NONE + + !f2py threadsafe + + LOGICAL :: fomp_in_final + + + + + fomp_in_final = .FALSE. + + +END FUNCTION fomp_in_final + + +SUBROUTINE fomp_init_lock(svar) + + + + USE omp_constants, ONLY : fomp_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_lock_kind), INTENT(OUT) :: svar + + + + + svar = -1 + + +END SUBROUTINE fomp_init_lock + + +SUBROUTINE fomp_init_nest_lock(nvar) + + + + USE omp_constants, ONLY : fomp_nest_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_nest_lock_kind), INTENT(OUT) :: nvar + + + + + nvar = -1 + + +END SUBROUTINE fomp_init_nest_lock + + +SUBROUTINE fomp_destroy_lock(svar) + + + + USE omp_constants, ONLY : fomp_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_lock_kind), INTENT(INOUT) :: svar + + + + + +END SUBROUTINE fomp_destroy_lock + + +SUBROUTINE fomp_destroy_nest_lock(nvar) + + + + USE omp_constants, ONLY : fomp_nest_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_nest_lock_kind), INTENT(INOUT) :: nvar + + + + + +END SUBROUTINE fomp_destroy_nest_lock + + +SUBROUTINE fomp_set_lock(svar) + + + + USE omp_constants, ONLY : fomp_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_lock_kind), INTENT(INOUT) :: svar + + + + + +END SUBROUTINE fomp_set_lock + + +SUBROUTINE fomp_set_nest_lock(nvar) + + + + USE omp_constants, ONLY : fomp_nest_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_nest_lock_kind), INTENT(INOUT) :: nvar + + + + + +END SUBROUTINE fomp_set_nest_lock + + +SUBROUTINE fomp_unset_lock(svar) + + + + USE omp_constants, ONLY : fomp_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_lock_kind), INTENT(INOUT) :: svar + + + + + +END SUBROUTINE fomp_unset_lock + + +SUBROUTINE fomp_unset_nest_lock(nvar) + + + + USE omp_constants, ONLY : fomp_nest_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_nest_lock_kind), INTENT(INOUT) :: nvar + + + + + +END SUBROUTINE fomp_unset_nest_lock + + +FUNCTION fomp_test_lock(svar) + + + + USE omp_constants, ONLY : fomp_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_lock_kind), INTENT(INOUT) :: svar + LOGICAL :: fomp_test_lock + + + + + fomp_test_lock = .FALSE. + + + + +END FUNCTION fomp_test_lock + + +FUNCTION fomp_test_nest_lock(nvar) + + + + USE omp_constants, ONLY : fomp_nest_lock_kind + + IMPLICIT NONE + + !f2py threadsafe + + INTEGER(KIND=fomp_nest_lock_kind), INTENT(INOUT) :: nvar + INTEGER :: fomp_test_nest_lock + + + + + fomp_test_nest_lock = -1 + + + + +END FUNCTION fomp_test_nest_lock + + +FUNCTION fomp_get_wtime() + + + + + IMPLICIT NONE + + !f2py threadsafe + + REAL (KIND=8) :: fomp_get_wtime + + + + + fomp_get_wtime = -1 + + + + +END FUNCTION fomp_get_wtime + + +FUNCTION fomp_get_wtick() + + + + + IMPLICIT NONE + + !f2py threadsafe + + REAL (KIND=8) :: fomp_get_wtick + + + + + fomp_get_wtick = -1 + + + + +END FUNCTION fomp_get_wtick + + diff --git a/fortran/ompgen.F90 b/fortran/ompgen.F90 index 2ac66e9..ed3d9bd 100644 --- a/fortran/ompgen.F90 +++ b/fortran/ompgen.F90 @@ -1,9 +1,49 @@ MODULE omp_constants #ifdef _OPENMP USE omp_lib - INTEGER, PARAMETER :: fomp_sched_kind = omp_sched_kind - INTEGER, PARAMETER :: fomp_nest_lock_kind = omp_nest_lock_kind - INTEGER, PARAMETER :: fomp_lock_kind = omp_lock_kind + ! f2py can't figure this out without me making a map of these kinds to + ! c types, so we're going to have to hard code the kinds below. + !INTEGER, PARAMETER :: fomp_sched_kind = omp_sched_kind + !INTEGER, PARAMETER :: fomp_nest_lock_kind = omp_nest_lock_kind + !INTEGER, PARAMETER :: fomp_lock_kind = omp_lock_kind + + ! Note: Defining these specifically is the only way I can get f2py to + ! work without doing the same thing in a mapping file. The values below + ! are for GNU on 64bit. This may not be entirely correct for non-GNU + ! compilers. In particular, it will be the locks that segfault/crash if + ! this is wrong. +#if defined(__GFORTRAN__) +#if (__SIZEOF_POINTER__ == 8) + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 8 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 8 +#else + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 4 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 4 +#endif +#elif defined(__INTEL_COMPILER_BUILD_DATE) +#if defined(__x86_64__) || defined(_M_X64) + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 8 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 8 +#else + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 4 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 4 +#endif +#elif defined(__PGI) +#if defined(__x86_64__) + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 8 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 8 +#else + INTEGER, PARAMETER :: fomp_sched_kind = 4 + INTEGER, PARAMETER :: fomp_lock_kind = 4 + INTEGER, PARAMETER :: fomp_nest_lock_kind = 4 +#endif +#endif + INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_static = omp_sched_static INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_dynamic = omp_sched_dynamic INTEGER(KIND=fomp_sched_kind), PARAMETER :: fomp_sched_guided = omp_sched_guided @@ -36,8 +76,6 @@ SUBROUTINE fomp_set_num_threads(num_threads) CALL omp_set_num_threads(num_threads) #endif - RETURN - END SUBROUTINE fomp_set_num_threads @@ -156,8 +194,6 @@ SUBROUTINE fomp_set_dynamic(dynamic_threads) CALL omp_set_dynamic(dynamic_threads) #endif - RETURN - END SUBROUTINE fomp_set_dynamic @@ -196,8 +232,6 @@ SUBROUTINE fomp_set_nested(nested) CALL omp_set_nested(nested) #endif - RETURN - END SUBROUTINE fomp_set_nested @@ -238,8 +272,6 @@ SUBROUTINE fomp_set_schedule(kind, modifier) CALL omp_set_schedule(kind, modifier) #endif - RETURN - END SUBROUTINE fomp_set_schedule @@ -263,8 +295,6 @@ SUBROUTINE fomp_get_schedule(kind, modifier) modifier = -1 #endif - RETURN - END SUBROUTINE fomp_get_schedule @@ -301,16 +331,12 @@ SUBROUTINE fomp_set_max_active_levels(max_levels) INTEGER, INTENT(IN) :: max_levels #else INTEGER, INTENT(IN) :: max_levels - - max_levels = -1 #endif #ifdef _OPENMP CALL omp_set_max_active_levels(max_levels) #endif - RETURN - END SUBROUTINE fomp_set_max_active_levels @@ -450,10 +476,10 @@ SUBROUTINE fomp_init_lock(svar) #ifdef _OPENMP CALL omp_init_lock(svar) +#else + svar = -1 #endif - RETURN - END SUBROUTINE fomp_init_lock @@ -471,10 +497,10 @@ SUBROUTINE fomp_init_nest_lock(nvar) #ifdef _OPENMP CALL omp_init_nest_lock(nvar) +#else + nvar = -1 #endif - RETURN - END SUBROUTINE fomp_init_nest_lock @@ -494,8 +520,6 @@ SUBROUTINE fomp_destroy_lock(svar) CALL omp_destroy_lock(svar) #endif - RETURN - END SUBROUTINE fomp_destroy_lock @@ -515,8 +539,6 @@ SUBROUTINE fomp_destroy_nest_lock(nvar) CALL omp_destroy_nest_lock(nvar) #endif - RETURN - END SUBROUTINE fomp_destroy_nest_lock @@ -536,8 +558,6 @@ SUBROUTINE fomp_set_lock(svar) CALL omp_set_lock(svar) #endif - RETURN - END SUBROUTINE fomp_set_lock @@ -557,8 +577,6 @@ SUBROUTINE fomp_set_nest_lock(nvar) CALL omp_set_nest_lock(nvar) #endif - RETURN - END SUBROUTINE fomp_set_nest_lock @@ -578,8 +596,6 @@ SUBROUTINE fomp_unset_lock(svar) CALL omp_unset_lock(svar) #endif - RETURN - END SUBROUTINE fomp_unset_lock @@ -599,8 +615,6 @@ SUBROUTINE fomp_unset_nest_lock(nvar) CALL omp_unset_nest_lock(nvar) #endif - RETURN - END SUBROUTINE fomp_unset_nest_lock @@ -623,9 +637,9 @@ FUNCTION fomp_test_lock(svar) fomp_test_lock = .FALSE. #endif - RETURN -END FUNCTION fomp_in_final + +END FUNCTION fomp_test_lock FUNCTION fomp_test_nest_lock(nvar) @@ -642,12 +656,12 @@ FUNCTION fomp_test_nest_lock(nvar) INTEGER :: fomp_test_nest_lock #ifdef _OPENMP - fomp_test_lock = omp_test_nest_lock(nvar) + fomp_test_nest_lock = omp_test_nest_lock(nvar) #else - fomp_test_lock = -1 + fomp_test_nest_lock = -1 #endif - RETURN + END FUNCTION fomp_test_nest_lock @@ -669,7 +683,7 @@ FUNCTION fomp_get_wtime() fomp_get_wtime = -1 #endif - RETURN + END FUNCTION fomp_get_wtime @@ -691,7 +705,7 @@ FUNCTION fomp_get_wtick() fomp_get_wtick = -1 #endif - RETURN + END FUNCTION fomp_get_wtick diff --git a/fortran/rip_cape.f90 b/fortran/rip_cape.f90 index d6a5fec..a56583e 100644 --- a/fortran/rip_cape.f90 +++ b/fortran/rip_cape.f90 @@ -40,7 +40,6 @@ REAL(KIND=8) FUNCTION TONPSADIABAT(thte, prs, psadithte, psadiprs, psaditmk, gam !!$OMP DECLARE SIMD (TONPSADIABAT) !!uniform(thte,prs,psadithte,psadiprs,psaditmk) !f2py threadsafe - !f2py intent(in,out) :: cape, cin IMPLICIT NONE REAL(KIND=8), INTENT(IN) :: thte diff --git a/fortran/wrffortran.pyf b/fortran/wrffortran.pyf index 41eecbb..8359fb7 100644 --- a/fortran/wrffortran.pyf +++ b/fortran/wrffortran.pyf @@ -33,6 +33,161 @@ python module _wrffortran ! in integer, optional,intent(in),check(shape(qvp,1)==mjx),depend(qvp) :: mjx=shape(qvp,1) integer, optional,intent(in),check(shape(qvp,2)==mkzh),depend(qvp) :: mkzh=shape(qvp,2) end subroutine deqthecalc + module omp_constants ! in :_wrffortran:omp.f90 + integer, parameter,optional :: fomp_nest_lock_kind=8 + integer(kind=4), parameter,optional :: fomp_sched_dynamic=2 + integer(kind=4), parameter,optional :: fomp_sched_guided=3 + integer, parameter,optional :: fomp_sched_kind=4 + integer(kind=4), parameter,optional :: fomp_sched_static=1 + integer, parameter,optional :: fomp_lock_kind=4 + integer(kind=4), parameter,optional :: fomp_sched_auto=4 + end module omp_constants + subroutine fomp_set_num_threads(num_threads) ! in :_wrffortran:omp.f90 + threadsafe + integer intent(in) :: num_threads + end subroutine fomp_set_num_threads + function fomp_get_num_threads() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_num_threads + end function fomp_get_num_threads + function fomp_get_max_threads() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_max_threads + end function fomp_get_max_threads + function fomp_get_thread_num() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_thread_num + end function fomp_get_thread_num + function fomp_get_num_procs() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_num_procs + end function fomp_get_num_procs + function fomp_in_parallel() ! in :_wrffortran:omp.f90 + threadsafe + logical :: fomp_in_parallel + end function fomp_in_parallel + subroutine fomp_set_dynamic(dynamic_threads) ! in :_wrffortran:omp.f90 + threadsafe + logical intent(in) :: dynamic_threads + end subroutine fomp_set_dynamic + function fomp_get_dynamic() ! in :_wrffortran:omp.f90 + threadsafe + logical :: fomp_get_dynamic + end function fomp_get_dynamic + subroutine fomp_set_nested(nested) ! in :_wrffortran:omp.f90 + threadsafe + logical intent(in) :: nested + end subroutine fomp_set_nested + function fomp_get_nested() ! in :_wrffortran:omp.f90 + threadsafe + logical :: fomp_get_nested + end function fomp_get_nested + subroutine fomp_set_schedule(kind,modifier) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_sched_kind + integer(kind=4) intent(in) :: kind + integer intent(in) :: modifier + end subroutine fomp_set_schedule + subroutine fomp_get_schedule(kind,modifier) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_sched_kind + integer(kind=4) intent(out) :: kind + integer intent(out) :: modifier + end subroutine fomp_get_schedule + function fomp_get_thread_limit() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_thread_limit + end function fomp_get_thread_limit + subroutine fomp_set_max_active_levels(max_levels) ! in :_wrffortran:omp.f90 + threadsafe + integer intent(in) :: max_levels + end subroutine fomp_set_max_active_levels + function fomp_get_max_active_levels() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_max_active_levels + end function fomp_get_max_active_levels + function fomp_get_level() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_level + end function fomp_get_level + function fomp_get_ancestor_thread_num(level) ! in :_wrffortran:omp.f90 + threadsafe + integer intent(in) :: level + integer :: fomp_get_ancestor_thread_num + end function fomp_get_ancestor_thread_num + function fomp_get_team_size(level) ! in :_wrffortran:omp.f90 + threadsafe + integer intent(in) :: level + integer :: fomp_get_team_size + end function fomp_get_team_size + function fomp_get_active_level() ! in :_wrffortran:omp.f90 + threadsafe + integer :: fomp_get_active_level + end function fomp_get_active_level + function fomp_in_final() ! in :_wrffortran:omp.f90 + threadsafe + logical :: fomp_in_final + end function fomp_in_final + subroutine fomp_init_lock(svar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_lock_kind + integer(kind=4) intent(out) :: svar + end subroutine fomp_init_lock + subroutine fomp_init_nest_lock(nvar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_nest_lock_kind + integer(kind=8) intent(out) :: nvar + end subroutine fomp_init_nest_lock + subroutine fomp_destroy_lock(svar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_lock_kind + integer(kind=4) intent(inout) :: svar + end subroutine fomp_destroy_lock + subroutine fomp_destroy_nest_lock(nvar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_nest_lock_kind + integer(kind=8) intent(inout) :: nvar + end subroutine fomp_destroy_nest_lock + subroutine fomp_set_lock(svar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_lock_kind + integer(kind=4) intent(inout) :: svar + end subroutine fomp_set_lock + subroutine fomp_set_nest_lock(nvar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_nest_lock_kind + integer(kind=8) intent(inout) :: nvar + end subroutine fomp_set_nest_lock + subroutine fomp_unset_lock(svar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_lock_kind + integer(kind=4) intent(inout) :: svar + end subroutine fomp_unset_lock + subroutine fomp_unset_nest_lock(nvar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_nest_lock_kind + integer(kind=8) intent(inout) :: nvar + end subroutine fomp_unset_nest_lock + function fomp_test_lock(svar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_lock_kind + integer(kind=4) intent(inout) :: svar + logical :: fomp_test_lock + end function fomp_test_lock + function fomp_test_nest_lock(nvar) ! in :_wrffortran:omp.f90 + threadsafe + use omp_constants, only: fomp_nest_lock_kind + integer(kind=8) intent(inout) :: nvar + integer :: fomp_test_nest_lock + end function fomp_test_nest_lock + function fomp_get_wtime() ! in :_wrffortran:omp.f90 + threadsafe + real(kind=8) :: fomp_get_wtime + end function fomp_get_wtime + function fomp_get_wtick() ! in :_wrffortran:omp.f90 + threadsafe + real(kind=8) :: fomp_get_wtick + end function fomp_get_wtick function tvirtual(temp,ratmix) ! in :_wrffortran:rip_cape.f90 threadsafe use wrf_constants, only: eps diff --git a/setup.py b/setup.py index 8f42dad..41ec9e6 100755 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ ext1 = numpy.distutils.core.Extension( "fortran/wrf_pw.f90", "fortran/wrf_vinterp.f90", "fortran/wrf_wind.f90", + "fortran/omp.f90", "fortran/wrffortran.pyf"] ) diff --git a/src/wrf/api.py b/src/wrf/api.py index c5dec8c..877096d 100644 --- a/src/wrf/api.py +++ b/src/wrf/api.py @@ -10,7 +10,23 @@ from .computation import (xy, interp1d, interp2dxy, interpz3d, slp, tk, td, rh, uvmet, smooth2d, cape_2d, cape_3d, cloudfrac, ctt, dbz, srhel, udhel, avo, pvo, eth, wetbulb, tvirtual, omega, pw) -from .extension import DiagnosticError +from .extension import (DiagnosticError, omp_set_num_threads, + omp_get_num_threads, + omp_get_max_threads, omp_get_thread_num, + omp_get_num_procs, omp_in_parallel, + omp_set_dynamic, omp_get_dynamic, omp_set_nested, + omp_get_nested, omp_set_schedule, + omp_get_schedule, omp_get_thread_limit, + omp_set_max_active_levels, + omp_get_max_active_levels, omp_get_level, + omp_get_ancestor_thread_num, omp_get_team_size, + omp_get_active_level, omp_in_final, + omp_init_lock, omp_init_nest_lock, + omp_destroy_lock, omp_destroy_nest_lock, + omp_set_lock, omp_set_nest_lock, + omp_unset_lock, omp_unset_nest_lock, + omp_test_lock, omp_test_nest_lock, + omp_get_wtime, omp_get_wtick) from .interp import (interplevel, vertcross, interpline, vinterp) from .latlon import (xy_to_ll, ll_to_xy, xy_to_ll_proj, ll_to_xy_proj) from .py3compat import (viewitems, viewkeys, viewvalues, isstr, py2round, @@ -49,7 +65,23 @@ __all__ += ["xy", "interp1d", "interp2dxy", "interpz3d", "slp", "tk", "td", "rh", "uvmet", "smooth2d", "cape_2d", "cape_3d", "cloudfrac", "ctt", "dbz", "srhel", "udhel", "avo", "pvo", "eth", "wetbulb", "tvirtual", "omega", "pw"] -__all__ += ["DiagnosticError"] +__all__ += ["DiagnosticError", "omp_set_num_threads", + "omp_get_num_threads", + "omp_get_max_threads", "omp_get_thread_num", + "omp_get_num_procs", "omp_in_parallel", + "omp_set_dynamic", "omp_get_dynamic", "omp_set_nested", + "omp_get_nested", "omp_set_schedule", + "omp_get_schedule", "omp_get_thread_limit", + "omp_set_max_active_levels", + "omp_get_max_active_levels", "omp_get_level", + "omp_get_ancestor_thread_num", "omp_get_team_size", + "omp_get_active_level", "omp_in_final", + "omp_init_lock", "omp_init_nest_lock", + "omp_destroy_lock", "omp_destroy_nest_lock", + "omp_set_lock", "omp_set_nest_lock", + "omp_unset_lock", "omp_unset_nest_lock", + "omp_test_lock", "omp_test_nest_lock", + "omp_get_wtime", "omp_get_wtick"] __all__ += ["interplevel", "vertcross", "interpline", "vinterp"] __all__ += ["xy_to_ll", "ll_to_xy", "xy_to_ll_proj", "ll_to_xy_proj"] __all__ += ["viewitems", "viewkeys", "viewvalues", "isstr", "py2round", diff --git a/src/wrf/constants.py b/src/wrf/constants.py index c8270db..8c62d37 100755 --- a/src/wrf/constants.py +++ b/src/wrf/constants.py @@ -4,7 +4,7 @@ from __future__ import (absolute_import, division, print_function, import numpy as np from .py3compat import viewitems -from wrf._wrffortran import wrf_constants +from wrf._wrffortran import wrf_constants, omp_constants #: Indicates that all times should be used in a diagnostic routine. ALL_TIMES = None @@ -15,6 +15,12 @@ class Constants(object): for key,val in viewitems(wrf_constants.__dict__): setattr(Constants, key.upper(), np.asscalar(val)) +setattr(Constants, "OMP_SCHED_STATIC", omp_constants.fomp_sched_static) +setattr(Constants, "OMP_SCHED_DYNAMIC", omp_constants.fomp_sched_dynamic) +setattr(Constants, "OMP_SCHED_GUIDED", omp_constants.fomp_sched_guided) +setattr(Constants, "OMP_SCHED_AUTO", omp_constants.fomp_sched_auto) + + class ConversionFactors(object): PA_TO_HPA = .01 PA_TO_TORR = 760.0/101325.0 @@ -29,6 +35,7 @@ class ConversionFactors(object): M_TO_FT = 3.28084 M_TO_MILES = .000621371 + class ProjectionTypes(object): ZERO = 0 LAMBERT_CONFORMAL = 1 diff --git a/src/wrf/extension.py b/src/wrf/extension.py index 777e29d..6887f87 100755 --- a/src/wrf/extension.py +++ b/src/wrf/extension.py @@ -12,7 +12,23 @@ from ._wrffortran import (dcomputetk, dinterp3dz, dinterp2dxy, dinterp1d, dcomputeabsvort, dlltoij, dijtoll, deqthecalc, omgcalc, virtual_temp, wetbulbcalc, dcomputepw, wrf_monotonic, wrf_vintrp, dcomputewspd, - dcomputewdir) + dcomputewdir, + fomp_set_num_threads, fomp_get_num_threads, + fomp_get_max_threads, fomp_get_thread_num, + fomp_get_num_procs, fomp_in_parallel, + fomp_set_dynamic, fomp_get_dynamic, fomp_set_nested, + fomp_get_nested, fomp_set_schedule, + fomp_get_schedule, fomp_get_thread_limit, + fomp_set_max_active_levels, + fomp_get_max_active_levels, fomp_get_level, + fomp_get_ancestor_thread_num, fomp_get_team_size, + fomp_get_active_level, fomp_in_final, + fomp_init_lock, fomp_init_nest_lock, + fomp_destroy_lock, fomp_destroy_nest_lock, + fomp_set_lock, fomp_set_nest_lock, + fomp_unset_lock, fomp_unset_nest_lock, + fomp_test_lock, fomp_test_nest_lock, + fomp_get_wtime, fomp_get_wtick) from .decorators import (left_iteration, cast_type, extract_and_transpose, check_args) @@ -908,5 +924,136 @@ def _wdir(u, v, outview=None): v) return result + + +# OpenMP wrappers + +def omp_set_num_threads(num_threads): + fomp_set_num_threads(num_threads) + + +def omp_get_num_threads(): + return fomp_get_num_threads() + + +def omp_get_max_threads(): + return fomp_get_max_threads() + + +def omp_get_thread_num(): + return fomp_get_thread_num() + + +def omp_get_num_procs(): + return fomp_get_num_procs() + + +def omp_in_parallel(): + return fomp_in_parallel() + + +def omp_set_dynamic(dynamic_threads): + fomp_set_dynamic(dynamic_threads) + + +def omp_get_dynamic(): + return fomp_get_dynamic() + + +def omp_set_nested(nested): + fomp_set_nested(nested) + + +def omp_get_nested(): + return fomp_get_nested() + + +def omp_set_schedule(kind, modifier): + fomp_set_schedule(kind, modifier) + + +def omp_get_schedule(): + return fomp_get_schedule() + + +def omp_get_thread_limit(): + return fomp_get_thread_limit() + + +def omp_set_max_active_levels(max_levels): + omp_set_max_active_levels(max_levels) + + +def omp_get_max_active_levels(): + return fomp_get_max_active_levels() + + +def omp_get_level(): + return fomp_get_level() + + +def omp_get_ancestor_thread_num(level): + return fomp_get_ancestor_thread_num(level) + + +def omp_get_team_size(level): + return fomp_get_team_size(level) + + +def omp_get_active_level(): + return fomp_get_active_level() + + +def omp_in_final(): + return fomp_in_final() + + +def omp_init_lock(): + return fomp_init_lock() + + +def omp_init_nest_lock(): + return fomp_init_nest_lock() + + +def omp_destroy_lock(svar): + fomp_destroy_lock(svar) + + +def omp_destroy_nest_lock(nvar): + fomp_destroy_nest_lock(nvar) + + +def omp_set_lock(svar): + fomp_set_lock(svar) + + +def omp_set_nest_lock(nvar): + fomp_set_nest_lock(nvar) + + +def omp_unset_lock(svar): + fomp_unset_lock(svar) + + +def omp_unset_nest_lock(nvar): + fomp_unset_nest_lock(nvar) + + +def omp_test_lock(svar): + return fomp_test_lock(svar) + + +def omp_test_nest_lock(nvar): + return fomp_test_nest_lock(nvar) + + +def omp_get_wtime(): + return fomp_get_wtime() + + +def omp_get_wtick(): + return fomp_get_wtick() +