Skip to content

Commit

Permalink
Add Intel tests to devel branch (#1547)
Browse files Browse the repository at this point in the history
Add the configuration files to run tests with an Intel compiler. Add
an environment variable `PYCCEL_DEFAULT_COMPILER` which
specifies the default compiler.

There are 3 failing tests due to:
- passing NaN as an argument
- #1540 

Additionally some array tests were modified to use `isclose` for
comparisons instead of `np.all_equal` these tests all involve divisions
and should have been using `isclose` anyway.

This is related to #542 but does not fully fix the issue as it only adds
Intel.

---------

Co-authored-by: Yaman Güçlü <yaman.guclu@gmail.com>
  • Loading branch information
EmilyBourne and yguclu committed Oct 13, 2023
1 parent 58bcff4 commit 17c6819
Show file tree
Hide file tree
Showing 13 changed files with 202 additions and 15 deletions.
68 changes: 68 additions & 0 deletions .github/actions/intel_install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: 'Intel installation commands'

runs:
using: "composite"
steps:
- name: update the package list
run:
sudo apt-get update
shell: bash
- name: Restore cached Intel
id: cache-intel-restore
uses: actions/cache/restore@v3
with:
path: |
/opt/intel/oneapi/
key: ${{ runner.os }}-intel-2023
restore-keys: |
${{ runner.os }}-intel-
- name: Install Intel OneAPI
if: steps.cache-intel-restore.outputs.cache-hit != 'true'
run: |
# See https://github.com/oneapi-src/oneapi-ci
wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
sudo apt-get update -o Dir::Etc::sourcelist="sources.list.d/oneAPI.list" -o APT::Get::List-Cleanup="0"
sudo apt-get install -y intel-oneapi-compiler-fortran intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic intel-oneapi-openmp intel-oneapi-mkl intel-oneapi-mpi-devel
shell: bash
- name: Save Intel environment variables
run: |
source /opt/intel/oneapi/setvars.sh
echo "$PATH" > $GITHUB_PATH
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >> $GITHUB_ENV
echo "LIBRARY_PATH=$LIBRARY_PATH" >> $GITHUB_ENV
echo "ONEAPI_ROOT=$ONEAPI_ROOT" >> $GITHUB_ENV
echo "MANPATH=$MANPATH" >> $GITHUB_ENV
echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" >> $GITHUB_ENV
echo "CMAKE_PREFIX_PATH=$CMAKE_PREFIX_PATH" >> $GITHUB_ENV
echo "TBB_ROOT=$TBB_ROOT" >> $GITHUB_ENV
echo "ONEAPI_ROOT=$ONEAPI_ROOT" >> $GITHUB_ENV
echo "ACL_BOARD_VENDOR_PATH=$ACL_BOARD_VENDOR_PATH" >> $GITHUB_ENV
echo "FPGA_VARS_DIR=$FPGA_VARS_DIR" >> $GITHUB_ENV
echo "I_MPI_ROOT=$I_MPI_ROOT" >> $GITHUB_ENV
echo "FI_PROVIDER_PATH=$FI_PROVIDER_PATH" >> $GITHUB_ENV
echo "DIAGUTIL_PATH=$DIAGUTIL_PATH" >> $GITHUB_ENV
echo "GDB_INFO=$GDB_INFO" >> $GITHUB_ENV
echo "CMPLR_ROOT=$CMPLR_ROOT" >> $GITHUB_ENV
echo "INFOPATH=$INFOPATH" >> $GITHUB_ENV
echo "OCL_ICD_FILENAMES=$OCL_ICD_FILENAMES" >> $GITHUB_ENV
echo "CLASSPATH=$CLASSPATH" >> $GITHUB_ENV
echo "INTELFPGAOCLSDKROOT=$INTELFPGAOCLSDKROOT" >> $GITHUB_ENV
echo "MKLROOT=$MKLROOT" >> $GITHUB_ENV
echo "NLSPATH=$NLSPATH" >> $GITHUB_ENV
echo "INTEL_PYTHONHOME=$INTEL_PYTHONHOME" >> $GITHUB_ENV
echo "CPATH=$CPATH" >> $GITHUB_ENV
mpicc --version
shell: bash
- name: Save Intel Cache
id: cache-intel-save
uses: actions/cache/save@v3
with:
path: |
/opt/intel/oneapi/
key: ${{ steps.cache-intel-restore.outputs.cache-primary-key }}
- name: Install Valgrind
run:
sudo apt-get install valgrind
shell: bash
106 changes: 106 additions & 0 deletions .github/workflows/intel.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Intel unit tests

on:
workflow_dispatch:
inputs:
python_version:
required: true
type: string
ref:
required: false
type: string
check_run_id:
required: false
type: string
pr_repo:
required: false
type: string
push:
branches: devel

env:
COMMIT: ${{ inputs.ref || github.event.ref }}
PEM: ${{ secrets.BOT_PEM }}
GITHUB_RUN_ID: ${{ github.run_id }}
GITHUB_CHECK_RUN_ID: ${{ inputs.check_run_id }}
PR_REPO: ${{ inputs.pr_repo || github.repository }}
PYCCEL_DEFAULT_COMPILER: 'intel'

jobs:
Python_version_picker:
runs-on: ubuntu-latest
if: github.event_name != 'push' || github.repository == 'pyccel/pyccel'
outputs:
python_version: ${{ steps.set-python_version.outputs.python_version }}
steps:
- if: github.event_name == 'push'
run: |
echo "version=3.9" >> $GITHUB_ENV
shell: bash
- id: dispatch-matrix
if: github.event_name == 'workflow_dispatch'
run: |
echo "version=${{ inputs.python_version }}" >> $GITHUB_ENV
shell: bash
- id: set-python_version
run: |
echo "python_version=$version" >> $GITHUB_OUTPUT
shell: bash

Intel:

runs-on: ubuntu-latest
name: Unit tests
needs: Python_version_picker

steps:
- uses: actions/checkout@v3
with:
ref: ${{ env.COMMIT }}
repository: ${{ env.PR_REPO }}
- name: Set up Python ${{ needs.Python_version_picker.outputs.python_version }}
uses: actions/setup-python@v4
with:
python-version: ${{ needs.Python_version_picker.outputs.python_version }}
- name: "Setup"
id: token
run: |
pip install jwt requests
python ci_tools/setup_check_run.py
- name: Install dependencies
uses: ./.github/actions/intel_install
- name: Install Pyccel with tests
run: |
python -m pip install --upgrade pip
python -m pip install .[test]
shell: bash
- name: Coverage install
uses: ./.github/actions/coverage_install
- name: Fortran/C tests with pytest
id: f_c_pytest
timeout-minutes: 60
uses: ./.github/actions/pytest_run
- name: Python tests with pytest
id: python_pytest
timeout-minutes: 20
uses: ./.github/actions/pytest_run_python
- name: Parallel tests with pytest
id: parallel
timeout-minutes: 20
uses: ./.github/actions/pytest_parallel
- name: Test with valgrind for memory leaks
id: valgrind
uses: ./.github/actions/valgrind_run
- name: Collect coverage information
continue-on-error: True
uses: ./.github/actions/coverage_collection
- name: Save code coverage report
uses: actions/upload-artifact@v3
with:
name: coverage-artifact
path: .coverage
retention-days: 1
- name: "Post completed"
if: always()
run:
python ci_tools/complete_check_run.py ${{ steps.f_c_pytest.outcome }} ${{ steps.python_pytest.outcome }} ${{ steps.parallel.outcome }} ${{ steps.valgrind.outcome }}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file.
- #1492 : Types of arguments for class methods can be declared like function arguments.
- #1511 : Add support for the `cmath` library.
- Output readable header syntax errors.
- New environment variable `PYCCEL_DEFAULT_COMPILER`.

### Fixed

Expand Down
1 change: 1 addition & 0 deletions ci_tools/bot_messages/show_tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ The following is a list of keywords which can be used to run tests. Tests in bol
- pickle_wheel : Checks that .pyccel files have been correctly generated and packaged into the wheel.
- linux_anaconda : Runs the unit tests on a linux system using anaconda for python.
- windows_anaconda : Runs the unit tests on a windows system using anaconda for python.
- intel : Runs the unit tests on a linux system using the intel compiler.

These tests can be run with the command `/bot run X` (multiple tests can be specified separated by spaces), or with `try V X` to test on Python version V.
4 changes: 3 additions & 1 deletion ci_tools/bot_tools/bot_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
'anaconda_windows': '3.10',
'coverage': '3.7',
'docs': '3.8',
'intel': '3.9',
'linux': '3.7',
'macosx': '3.10',
'pickle_wheel': '3.7',
Expand All @@ -30,6 +31,7 @@
'anaconda_windows': "Unit tests on Windows with anaconda",
'coverage': "Coverage verification",
'docs': "Check documentation",
'intel': "Unit tests on Linux with Intel compiler",
'linux': "Unit tests on Linux",
'macosx': "Unit tests on MacOSX",
'pickle_wheel': "Test pickling during wheel installation",
Expand Down Expand Up @@ -415,7 +417,7 @@ def is_test_required(self, commit_log, name, key, state):
True if the test should be run, False otherwise.
"""
print("Checking : ", name)
if key in ('linux', 'windows', 'macosx', 'anaconda_linux', 'anaconda_windows', 'coverage'):
if key in ('linux', 'windows', 'macosx', 'anaconda_linux', 'anaconda_windows', 'coverage', 'intel'):
has_relevant_change = lambda diff: any((f.startswith('pyccel/') or f.startswith('tests/')) \
and f.endswith('.py') and f != 'pyccel/version.py' \
for f in diff) #pylint: disable=unnecessary-lambda-assignment
Expand Down
1 change: 1 addition & 0 deletions ci_tools/devel_branch_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
bot.run_tests(['pickle_wheel'], '3.7', force_run = True)
bot.run_tests(['anaconda_linux'], '3.10', force_run = True)
bot.run_tests(['anaconda_windows'], '3.10', force_run = True)
bot.run_tests(['intel'], '3.9', force_run = True)
2 changes: 2 additions & 0 deletions docs/compiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ or
epyccel(my_func, compiler='intel')
```

It is also possible to change the default compiler family by setting the environment variable `PYCCEL_DEFAULT_COMPILER`.

## User-defined compiler

The user can also define their own compiler in a JSON file. To use this definition, the location of the JSON file must be passed to the _compiler_ argument. The JSON file must define the following:
Expand Down
2 changes: 1 addition & 1 deletion pyccel/codegen/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def handle_error(stage):

# Choose Fortran compiler
if compiler is None:
compiler = 'GNU'
compiler = os.environ.get('PYCCEL_DEFAULT_COMPILER', 'GNU')

fflags = [] if fflags is None else fflags.split()
wrapper_flags = [] if wrapper_flags is None else wrapper_flags.split()
Expand Down
8 changes: 4 additions & 4 deletions pyccel/compilers/default_compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@

#------------------------------------------------------------
nvfort_info = {'exec' : 'nvfort',
'mpi_exec' : 'nvfort',
'mpi_exec' : 'mpifort',
'language': 'fortran',
'module_output_flag': '-module',
'debug_flags': ("-Mbounds","-g","-O0"),
Expand Down Expand Up @@ -123,8 +123,8 @@
gcc_info['mpi']['libdirs'] = (os.environ["MSMPI_LIB64"].rstrip('\\'),)

#------------------------------------------------------------
icc_info = {'exec' : 'icc',
'mpi_exec' : 'mpiicc',
icc_info = {'exec' : 'icx',
'mpi_exec' : 'mpicc',
'language': 'c',
'debug_flags': ("-g","-O0"),
'release_flags': ("-O3","-funroll-loops",),
Expand Down Expand Up @@ -158,7 +158,7 @@

#------------------------------------------------------------
nvc_info = {'exec' : 'nvc',
'mpi_exec' : 'nvc',
'mpi_exec' : 'mpicc',
'language': 'c',
'debug_flags': ("-g","-O0"),
'release_flags': ("-O3","-Munroll",),
Expand Down
2 changes: 2 additions & 0 deletions tests/epyccel/recognised_functions/test_cmath_funcs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# pylint: disable=missing-function-docstring, missing-module-docstring
from cmath import nanj, infj, pi
import os
import sys

import pytest
Expand Down Expand Up @@ -257,6 +258,7 @@ def tanh_phrase(x : complex, y : complex):
)
)
)
@pytest.mark.skipif(os.environ.get('PYCCEL_DEFAULT_COMPILER', None) == 'intel', reason='Nan not correctly passed to intel function')
def test_isfinite_call(language): # isfinite
@template('T', [float, complex])
def isfinite_call(x : 'T'):
Expand Down
2 changes: 2 additions & 0 deletions tests/epyccel/recognised_functions/test_math_funcs.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# pylint: disable=missing-function-docstring, missing-module-docstring
from math import nan, inf, modf
import os
import sys
import pytest
from numpy.random import rand, randint, uniform
Expand Down Expand Up @@ -539,6 +540,7 @@ def copysign_return_type(x : 'float', y : 'int'):
)
)
)
@pytest.mark.skipif(os.environ.get('PYCCEL_DEFAULT_COMPILER', None) == 'intel', reason='Nan not correctly passed to intel function')
def test_isfinite_call(language): # isfinite
def isfinite_call(x : 'float'):
from math import isfinite
Expand Down
19 changes: 10 additions & 9 deletions tests/epyccel/test_arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
from pyccel.epyccel import epyccel
from modules import arrays

RTOL = 1e-12
ATOL = 1e-16

def check_array_equal(a, b):
"""
Check that two arrays are equal.
Expand Down Expand Up @@ -1102,7 +1105,7 @@ def test_array_float_1d_scalar_div(language):
f1(x1, a)
f2(x2, a)

assert np.array_equal( x1, x2 )
assert np.allclose(x1, x2, rtol=RTOL, atol=ATOL)

def test_array_float_1d_scalar_mod(language):
f1 = arrays.array_float_1d_scalar_mod
Expand Down Expand Up @@ -1273,7 +1276,7 @@ def test_array_float_2d_C_scalar_div(language):
f1(x1, a)
f2(x2, a)

assert np.array_equal( x1, x2 )
assert np.allclose(x1, x2, rtol=RTOL, atol=ATOL)

def test_array_float_2d_C_scalar_mod(language):

Expand Down Expand Up @@ -1476,7 +1479,7 @@ def test_array_float_2d_F_scalar_div(language):
f1(x1, a)
f2(x2, a)

assert np.array_equal( x1, x2 )
assert np.allclose(x1, x2, rtol=RTOL, atol=ATOL)

def test_array_float_2d_F_scalar_mod(language):

Expand Down Expand Up @@ -1802,13 +1805,13 @@ def test_multiple_stack_array_1(language):

f1 = arrays.multiple_stack_array_1
f2 = epyccel(f1, language = language)
assert np.equal(f1(), f2())
assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)

def test_multiple_stack_array_2(language):

f1 = arrays.multiple_stack_array_2
f2 = epyccel(f1, language = language)
assert np.equal(f1(), f2())
assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)

#==============================================================================
# TEST: 2D Stack ARRAYS OF REAL
Expand All @@ -1834,13 +1837,13 @@ def test_multiple_2d_stack_array_1(language):

f1 = arrays.multiple_2d_stack_array_1
f2 = epyccel(f1, language = language)
assert np.equal(f1(), f2())
assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)

def test_multiple_2d_stack_array_2(language):

f1 = arrays.multiple_2d_stack_array_2
f2 = epyccel(f1, language = language)
assert np.equal(f1(), f2())
assert np.allclose(f1(), f2(), rtol=RTOL, atol=ATOL)

#==============================================================================
# TEST: Product and matrix multiplication
Expand Down Expand Up @@ -3569,8 +3572,6 @@ def test_arrs_2d_negative_index(language):
#==============================================================================
# TEST : NUMPY ARANGE
#==============================================================================
RTOL = 1e-12
ATOL = 1e-16

def test_numpy_arange_one_arg(language):
f1 = arrays.arr_arange_1
Expand Down
1 change: 1 addition & 0 deletions tests/epyccel/test_epyccel_openmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ def test_omp_arraysum_combined(language):
assert f1(x) == np.sum(x)

@pytest.mark.external
@pytest.mark.xfail(os.environ.get('PYCCEL_DEFAULT_COMPILER', None) == 'intel', reason='#1539')
def test_omp_range_sum_critical(language):
f1 = epyccel(openmp.omp_range_sum_critical, fflags = '-Wall', accelerators=['openmp'], language=language)

Expand Down

0 comments on commit 17c6819

Please sign in to comment.