rookiehpc / rookiehpc.github.io

A website covering major HPC technologies, designed to welcome contributions.
GNU Affero General Public License v3.0
56 stars 12 forks source link

Missing masked and reference primary (deprecation of master) #261

Open mathomp4 opened 2 years ago

mathomp4 commented 2 years ago

Mainly an FYI.

In recent (OpenMP 5?) versions of the standard have pretty much changed any reference of "master" to "primary" (for reasons much like why GitHub defaults to "main" and not "master".

For example, for copyin the Standard now reads (emphasis mine):

The copyin clause provides a mechanism to copy the value of a threadprivate variable of the primary thread to the threadprivate variable of each other member of the team that is executing the parallel region.

And in the deprecation section:

  • The master affinity policy was deprecated.
  • The master construct and all combined and composite constructs of which it is a constituent construct were deprecated.

(ETA: Removed examples because examples were...not relevant!)

rookiehpc commented 2 years ago

Well spotted @mathomp4; the versions 5.1 and 5.2 of the OpenMP standard no longer have such mentions indeed, and each does mention that master constructs are now deprecated.

The tricky aspect indeed will be to find out when to do the switch in the examples in this repository.

One potential solution in future could be to duplicate all OpenMP examples, replacing any master occurence with its primary counterpart:

mathomp4 commented 2 years ago

@rookiehpc You are right. I thought they'd also replaced the omp master with omp primary but no, it was removed. They did change all references to "master process" with "primary process" and things like proc_bind now have a primary instead of master setting.

For now I've removed my "example" above since it can never work. There is no omp primary construct. It looks like the fancier omp masked is now the equivalent.

If I do sed on your omp master example with omp masked GCC 12.1, Intel 2022.1 and NAG 7.1 are happy:

❯ gfortran --version
GNU Fortran (GCC) 12.1.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

❯ gfortran -fopenmp test.masked.F90 && ./a.out
(Thread 2) Every thread executes this printf.
(Thread 3) Every thread executes this printf.
(Thread 0) Every thread executes this printf.
(Thread 1) Every thread executes this printf.
(Thread 0) Only the masked thread executes this printf, which is me.

❯ ifort -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.6.0 Build 20220226_000000
Copyright (C) 1985-2022 Intel Corporation.  All rights reserved.

❯ ifort -qopenmp test.masked.F90 && ./a.out
(Thread 0) Every thread executes this printf.
(Thread 2) Every thread executes this printf.
(Thread 1) Every thread executes this printf.
(Thread 3) Every thread executes this printf.
(Thread 0) Only the masked thread executes this printf, which is me.

❯ nagfor -openmp test.masked.F90 && ./a.out
NAG Fortran Compiler Release 7.1(Hanzomon) Build 7110
Extension(OpenMP5.1): test.masked.F90, line 18: OpenMP MASKED construct
[NAG Fortran Compiler normal termination]
(Thread 0) Every thread executes this printf.
(Thread 3) Every thread executes this printf.
(Thread 2) Every thread executes this printf.
(Thread 1) Every thread executes this printf.
(Thread 0) Only the masked thread executes this printf, which is me.

Maybe this isn't as bad as I thought! 😄

mathomp4 commented 2 years ago

And ooh, I like masked filter. Using your example:

        !$omp masked filter(2)
            WRITE(*,'(A,I0,A)') '(Thread ', omp_get_thread_num(), ') Only the masked thread executes this printf, which is me.'
        !$omp end masked

and then:

❯ nagfor -openmp test.masked.filter.F90 && ./a.out
NAG Fortran Compiler Release 7.1(Hanzomon) Build 7110
Extension(OpenMP5.1): test.masked.filter.F90, line 18: OpenMP MASKED construct
[NAG Fortran Compiler normal termination]
(Thread 0) Every thread executes this printf.
(Thread 2) Every thread executes this printf.
(Thread 1) Every thread executes this printf.
(Thread 3) Every thread executes this printf.
(Thread 2) Only the masked thread executes this printf, which is me.

Fun. Now thread two does the masked print!