Skip to content

Commit

Permalink
Improve and test Pyccel compiler flags (#428)
Browse files Browse the repository at this point in the history
- Add compiler flags for GFortran >= 14 on Apple silicon chips
- Add unit test in `test_epyccel_flags.py` to check compiler flags
passed to `epyccel`
- Update GitHub actions used in documentation workflow
  • Loading branch information
yguclu authored Sep 6, 2024
1 parent 1f338bc commit 43833c2
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 11 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,9 @@ jobs:
python -m pip install .
python -m pip freeze
- name: Test pyccel optimization flags
- name: Test Pyccel optimization flags
run: |
pyccel --verbose ./psydac/linalg/kernels/axpy_kernels.py
pytest --pyargs psydac -m pyccel --capture=no
- name: Initialize test directory
run: |
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN}}
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install non-Python dependencies on Ubuntu
Expand All @@ -37,9 +37,9 @@ jobs:
make -C docs html
python docs/update_links.py
- name: Setup Pages
uses: actions/configure-pages@v3
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
uses: actions/upload-pages-artifact@v3
with:
path: 'docs/build/html'

Expand All @@ -53,4 +53,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
uses: actions/deploy-pages@v4
19 changes: 15 additions & 4 deletions psydac/api/settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# coding: utf-8
import subprocess # nosec B404
import platform
import re
from packaging.version import Version


__all__ = ('PSYDAC_DEFAULT_FOLDER', 'PSYDAC_BACKENDS')
Expand Down Expand Up @@ -40,18 +43,26 @@
'openmp' : False}
# ...

# Get gfortran version
gfortran_version_output = subprocess.check_output(['gfortran', '--version']).decode('utf-8') # nosec B603, B607
gfortran_version_string = re.search("(\d+\.\d+\.\d+)", gfortran_version_output).group()
gfortran_version = Version(gfortran_version_string)

# Platform-dependent flags
if platform.system() == "Darwin" and platform.machine() == 'arm64':
if platform.system() == "Darwin" and platform.machine() == 'arm64' and gfortran_version >= Version("14"):

# Apple silicon requires architecture-specific flags (see https://github.com/pyccel/psydac/pull/411)
import subprocess # nosec B404
# which are only available on GCC version >= 14
cpu_brand = subprocess.check_output(['sysctl','-n','machdep.cpu.brand_string']).decode('utf-8') # nosec B603, B607
if "Apple M1" in cpu_brand:
PSYDAC_BACKEND_GPYCCEL['flags'] += ' -mcpu=apple-m1'
if "Apple M1" in cpu_brand: PSYDAC_BACKEND_GPYCCEL['flags'] += ' -mcpu=apple-m1'
elif "Apple M2" in cpu_brand: PSYDAC_BACKEND_GPYCCEL['flags'] += ' -mcpu=apple-m2'
elif "Apple M3" in cpu_brand: PSYDAC_BACKEND_GPYCCEL['flags'] += ' -mcpu=apple-m3'
else:
# TODO: Support later Apple CPU models. Perhaps the CPU naming scheme could be easily guessed
# based on the output of 'sysctl -n machdep.cpu.brand_string', but I wouldn't rely on this
# guess unless it has been manually verified. Loud errors are better than silent failures!
raise SystemError(f"Unsupported Apple CPU '{cpu_brand}'.")

else:
# Default architecture flags
PSYDAC_BACKEND_GPYCCEL['flags'] += ' -march=native -mtune=native'
Expand Down
35 changes: 35 additions & 0 deletions psydac/api/tests/test_epyccel_flags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import pytest


@pytest.mark.pyccel
def test_epyccel_flags():

from pyccel.epyccel import epyccel
from psydac.api.settings import PSYDAC_BACKEND_GPYCCEL as backend

kwargs = {'language' : 'fortran',
'compiler' : backend['compiler'],
'fflags' : backend['flags'],
'accelerators' : ['openmp'] if backend['openmp'] else [],
'verbose' : True,
}

# Function to be Pyccel-ized
def f(x : float):
return 3 * x

# Pyccel magic
# ------------
# Fortran code is generated and then compiled with the selected compiler.
# The compiled function is callable from Python through the C Python API.
# The necessary C wrapper functions are also generated by Pyccel.
fast_f = epyccel(f, **kwargs)

# Check output of pyccelized function
assert fast_f(3.5) == f(3.5)


# Interactive usage
if __name__ == '__main__':
test_epyccel_flags()
print('PASSED')
1 change: 1 addition & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ markers =
serial: single-process test,
parallel: test to be run using 'mpiexec',
petsc: test requiring a working PETSc installation with petsc4py Python bindings
pyccel: test for checking Pyccel setup on machine

python_files = test_*.py
python_classes =
Expand Down

0 comments on commit 43833c2

Please sign in to comment.