diff --git a/.github/utils/CheckExamples/CMakeLists.txt b/.github/utils/CheckExamples/CMakeLists.txt new file mode 100644 index 0000000..223e96f --- /dev/null +++ b/.github/utils/CheckExamples/CMakeLists.txt @@ -0,0 +1,50 @@ +# Checks that all "example codes" in the `Checks/` folders are compilable to +# avoid committing incorrect examples. It's done here, separately and in bulk, +# so that no overhead is added by default when submitting a new check. You'll +# hopefully only have to know this exists if your example fails to compile + +cmake_minimum_required(VERSION 3.25) +project("Test that the check examples compile") + +enable_language(Fortran) +# Build them as libraries, not executables +set (CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set (BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../Checks) +message(STATUS "Looking for files in '${BASE_DIR}'") + +# The non-recursive glob only includes files in the first level directory of the +# Checks which is where the examples are usually located. This way we avoid +# benchmark programs which may be harder to compile and will be checked anyways +# by the benchmark running script +file(GLOB check_files + ${BASE_DIR}/*/*.c + ${BASE_DIR}/*/*.cpp + ${BASE_DIR}/*/*.f + ${BASE_DIR}/*/*.F + ${BASE_DIR}/*/*.f90 + ${BASE_DIR}/*/*.F90 +) + +# PWR068: Has a module file that has to be compiled in order, and a compilation error on purpose +# PWD003, PWD006: GFortran catches the data transfer error +set (excluded_checks_regex "PWR068|PWD003|PWD006") + +list(FILTER check_files EXCLUDE REGEX ${excluded_checks_regex}) + +foreach(check_file ${check_files}) + message(CHECK_START "Trying to compile ${check_file}") + set (extra_flags "-fopenmp -fopenacc") + try_compile( + TRY_RESULT ${CMAKE_BINARY_DIR} + SOURCES ${check_file} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${extra_flags} + OUTPUT_VARIABLE TRY_RESULT_OUTPUT + ) + + if (TRY_RESULT) + message(CHECK_PASS "Good") + else() + message(CHECK_FAIL "Bad:\n ${TRY_RESULT_OUTPUT}") + endif() +endforeach() diff --git a/.github/workflows/compile-check-examples.yml b/.github/workflows/compile-check-examples.yml new file mode 100644 index 0000000..4de6b42 --- /dev/null +++ b/.github/workflows/compile-check-examples.yml @@ -0,0 +1,19 @@ +name: Compile Check examples + +on: + push: + paths: + - '.github/workflows/**' + - '.github/utils/CheckExamples/**' + - 'Checks/**' + +jobs: + # Let us run this job on Ubuntu only, so we can check at the moment that + # examples compile at least on GCC && GFortran + compile-check-examples: + runs-on: ubuntu-24.04 + steps: + - name: Check out repository + uses: actions/checkout@v4 + - name: Check that all check examples compile + run: cmake -B build -DCMAKE_C_COMPILER=gcc -DCMAKE_Fortran_COMPILER=gfortran -S .github/utils/CheckExamples/ diff --git a/Checks/PWD003/example-omp.c b/Checks/PWD003/example-omp.c index a128535..b2bf55e 100644 --- a/Checks/PWD003/example-omp.c +++ b/Checks/PWD003/example-omp.c @@ -4,7 +4,7 @@ void example(int *a, int *b, int *sum, int size) { // Array bounds should be specified #pragma omp target map(to: a, b) map(from: sum) - #pragma omp parallel for default(none) shared(a, b, sum) + #pragma omp parallel for default(none) shared(a, b, sum, size) for (int i = 0; i < size; i++) { sum[i] = a[i] + b[i]; } diff --git a/Checks/PWD003/example-omp.f90 b/Checks/PWD003/example-omp.f90 index 270de23..e4f23dc 100644 --- a/Checks/PWD003/example-omp.f90 +++ b/Checks/PWD003/example-omp.f90 @@ -10,7 +10,7 @@ subroutine example(a, b, sum, size) ! Array bounds should be specified !$omp target map(to: a, b) map(from: sum) - !$omp parallel do default(none) shared(a, b, sum) + !$omp parallel do default(none) shared(a, b, sum, size) do i = 1, size sum(i) = a(i) + b(i) end do diff --git a/Checks/PWD009/README.md b/Checks/PWD009/README.md index 1763111..55bb891 100644 --- a/Checks/PWD009/README.md +++ b/Checks/PWD009/README.md @@ -25,7 +25,7 @@ on non-overlapping positions of the array: void example(int m, double *A, double *B, double *C) { double temp; - #pragma omp parallel for default(none) private(i, temp, C) shared(A, B, m) + #pragma omp parallel for default(none) private(temp, C) shared(A, B, m) for (int i = 0; i < m; i++) { temp = A[i] * B[i]; C[i] = C[i] + temp; @@ -39,7 +39,7 @@ To fix this, `C` should be moved to a `shared` clause: void example(int m, double *A, double *B, double *C) { double temp; - #pragma omp parallel for default(none) private(i, temp) shared(A, B, C, m) + #pragma omp parallel for default(none) private(temp) shared(A, B, C, m) for (int i = 0; i < m; i++) { temp = A[i] * B[i]; C[i] = C[i] + temp; diff --git a/Checks/PWD009/example-omp.c b/Checks/PWD009/example-omp.c index 2824b2a..51b47f4 100644 --- a/Checks/PWD009/example-omp.c +++ b/Checks/PWD009/example-omp.c @@ -4,7 +4,7 @@ void example(int m, double *A, double *B, double *C) { double temp; // "C" should be shared - #pragma omp parallel for default(none) private(i, temp, C) shared(A, B, m) + #pragma omp parallel for default(none) private(temp, C) shared(A, B, m) for (int i = 0; i < m; i++) { temp = A[i] * B[i]; C[i] = C[i] + temp; diff --git a/Checks/PWR006/README.md b/Checks/PWR006/README.md index 56c0fcb..71a6ab2 100644 --- a/Checks/PWR006/README.md +++ b/Checks/PWR006/README.md @@ -32,7 +32,7 @@ void example() { int B[SIZE] = {5, 4, 3, 2, 1}; int sum[SIZE]; - #pragma omp parallel for shared(sum) firstprivate(A, B) private(i) + #pragma omp parallel for shared(sum) firstprivate(A, B) for (int i = 0; i < SIZE; i++) { sum[i] = A[i] + B[i]; } @@ -51,7 +51,7 @@ void example() { int B[SIZE] = {5, 4, 3, 2, 1}; int sum[SIZE]; - #pragma omp parallel for shared(sum, A, B) private(i) + #pragma omp parallel for shared(sum, A, B) for (int i = 0; i < SIZE; i++) { sum[i] = A[i] + B[i]; } diff --git a/Checks/PWR006/example.c b/Checks/PWR006/example.c index 10e2dbf..33d7ac3 100644 --- a/Checks/PWR006/example.c +++ b/Checks/PWR006/example.c @@ -7,7 +7,7 @@ void example() { int B[SIZE] = {5, 4, 3, 2, 1}; int sum[SIZE]; - #pragma omp parallel for shared(sum) firstprivate(A, B) private(i) + #pragma omp parallel for shared(sum) firstprivate(A, B) for (int i = 0; i < SIZE; i++) { sum[i] = A[i] + B[i]; } diff --git a/Checks/PWR013/README.md b/Checks/PWR013/README.md index 9aa39cb..2297bdc 100644 --- a/Checks/PWR013/README.md +++ b/Checks/PWR013/README.md @@ -27,7 +27,7 @@ used: ```c void example(double *A, double *B, double *C) { #pragma omp target teams distribute parallel for schedule(auto) shared(A, B) \ - private(i) map(to: A[0:100], B[0:100]) map(tofrom: C[0:100]) + map(to: A[0:100], B[0:100]) map(tofrom: C[0:100]) for (int i = 0; i < 100; i++) { C[i] += A[i]; } @@ -39,7 +39,7 @@ This can be easily corrected by removing references to B from all the clauses: ```c void example(double *A, double *B, double *C) { #pragma omp target teams distribute parallel for schedule(auto) shared(A) \ - private(i) map(to: A[0:100]) map(tofrom: C[0:100]) + map(to: A[0:100]) map(tofrom: C[0:100]) for (int i = 0; i < 100; i++) { C[i] += A[i]; } diff --git a/Checks/PWR013/example-omp.c b/Checks/PWR013/example-omp.c index 026fb25..666e9da 100644 --- a/Checks/PWR013/example-omp.c +++ b/Checks/PWR013/example-omp.c @@ -2,7 +2,7 @@ void example(double *A, double *B, double *C) { #pragma omp target teams distribute parallel for schedule(auto) shared(A, B) \ - private(i) map(to: A[0:100], B[0:100]) map(tofrom: C[0:100]) + map(to: A[0:100], B[0:100]) map(tofrom: C[0:100]) for (int i = 0; i < 100; i++) { C[i] += A[i]; } diff --git a/Checks/PWR015/example-omp.c b/Checks/PWR015/example-omp.c index e74fc2d..3aab03b 100644 --- a/Checks/PWR015/example-omp.c +++ b/Checks/PWR015/example-omp.c @@ -3,7 +3,7 @@ void example() { int A[100], B[100], sum[100]; #pragma omp target map(to: A[0:100], B[0:100]) map(from: sum[0:100]) - #pragma omp parallel for private(i) + #pragma omp parallel for for (int i = 0; i < 50; i++) { sum[i] = A[i] + B[i]; }