Skip to content

Commit 85f0602

Browse files
bauomEmilyBourne
authored andcommitted
[init] Adding CUDA language/compiler and CodePrinter (#32)
This PR aims to make the C code compilable using nvcc. The cuda language was added as well as a CudaCodePrinter. Changes to stdlib: Wrapped expressions using complex types in an `ifndef __NVCC__` to avoid processing them with the nvcc compiler --------- Co-authored-by: Mouad Elalj, EmilyBourne
1 parent cce910c commit 85f0602

File tree

18 files changed

+298
-83
lines changed

18 files changed

+298
-83
lines changed

.dict_custom.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ Valgrind
108108
variadic
109109
subclasses
110110
oneAPI
111+
Cuda
111112
getter
112113
setter
113114
bitwise

.github/actions/pytest_parallel/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ runs:
1010
steps:
1111
- name: Test with pytest
1212
run: |
13-
mpiexec -n 4 ${MPI_OPTS} python -m pytest epyccel/test_parallel_epyccel.py -v -m parallel -rXx
14-
#mpiexec -n 4 ${MPI_OPTS} python -m pytest epyccel -v -m parallel -rXx
13+
mpiexec -n 4 ${MPI_OPTS} python -m pytest epyccel/test_parallel_epyccel.py -v -m "parallel and not cuda" -rXx
14+
#mpiexec -n 4 ${MPI_OPTS} python -m pytest epyccel -v -m "parallel and not cuda" -rXx
1515
shell: ${{ inputs.shell_cmd }}
1616
working-directory: ./tests
1717

.github/actions/pytest_run/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@ runs:
5151
working-directory: ./tests
5252
id: pytest_3
5353
- name: Test Fortran translations
54-
run: python -m pytest -n auto -rX ${FLAGS} -m "not (parallel or xdist_incompatible) and not (c or python or ccuda) ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s4_outfile.out
54+
run: python -m pytest -n auto -rX ${FLAGS} -m "not (parallel or xdist_incompatible) and not (c or python or cuda) ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s4_outfile.out
5555
shell: ${{ inputs.shell_cmd }}
5656
working-directory: ./tests
5757
id: pytest_4
5858
- name: Test multi-file Fortran translations
5959
run: |
60-
python -m pytest -rX ${FLAGS} -m "xdist_incompatible and not parallel and not (c or python or ccuda) ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s5_outfile.out
60+
python -m pytest -rX ${FLAGS} -m "xdist_incompatible and not parallel and not (c or python or cuda) ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s5_outfile.out
6161
pyccel-clean
6262
shell: ${{ inputs.shell_cmd }}
6363
working-directory: ./tests

.github/actions/pytest_run_cuda/action.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: 'Pyccel pytest commands generating Ccuda'
1+
name: 'Pyccel pytest commands generating Cuda'
22
inputs:
33
shell_cmd:
44
description: 'Specifies the shell command (different for anaconda)'
@@ -11,7 +11,14 @@ runs:
1111
- name: Ccuda tests with pytest
1212
run: |
1313
# Catch exit 5 (no tests found)
14-
sh -c 'python -m pytest -n auto -rx -m "not (parallel or xdist_incompatible) and ccuda" --ignore=symbolic --ignore=ndarrays; ret=$?; [ $ret = 5 ] && exit 0 || exit $ret'
14+
python -m pytest -rX ${FLAGS} -m "not (xdist_incompatible or parallel) and cuda ${{ inputs.pytest_mark }}" --ignore=symbolic --ignore=ndarrays 2>&1 | tee s1_outfile.out
1515
pyccel-clean
1616
shell: ${{ inputs.shell_cmd }}
1717
working-directory: ./tests
18+
- name: Final step
19+
if: always()
20+
id: status
21+
run:
22+
python ci_tools/json_pytest_output.py -t "Cuda Test Summary" --tests "Cuda tests:${{ steps.pytest_1.outcome }}:tests/s1_outfile.out"
23+
24+
shell: ${{ inputs.shell_cmd }}

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
# Change Log
22
All notable changes to this project will be documented in this file.
33

4+
## \[Cuda - UNRELEASED\]
5+
6+
### Added
7+
8+
- #32 : add support for `nvcc` Compiler and `cuda` language as a possible option.
9+
410
## \[UNRELEASED\]
511

612
### Added

pyccel/codegen/codegen.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
from pyccel.codegen.printing.fcode import FCodePrinter
1010
from pyccel.codegen.printing.ccode import CCodePrinter
1111
from pyccel.codegen.printing.pycode import PythonCodePrinter
12+
from pyccel.codegen.printing.cucode import CudaCodePrinter
1213

1314
from pyccel.ast.core import FunctionDef, Interface, ModuleHeader
1415
from pyccel.utilities.stage import PyccelStage
1516

16-
_extension_registry = {'fortran': 'f90', 'c':'c', 'python':'py'}
17-
_header_extension_registry = {'fortran': None, 'c':'h', 'python':None}
17+
_extension_registry = {'fortran': 'f90', 'c':'c', 'python':'py', 'cuda':'cu'}
18+
_header_extension_registry = {'fortran': None, 'c':'h', 'python':None, 'cuda':'h'}
1819
printer_registry = {
1920
'fortran':FCodePrinter,
2021
'c':CCodePrinter,
21-
'python':PythonCodePrinter
22+
'python':PythonCodePrinter,
23+
'cuda':CudaCodePrinter
2224
}
2325

2426
pyccel_stage = PyccelStage()

pyccel/codegen/compiling/compilers.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,10 @@ def compile_shared_library(self, compile_obj, output_folder, verbose = False, sh
441441
# Collect compile information
442442
exec_cmd, includes, libs_flags, libdirs_flags, m_code = \
443443
self._get_compile_components(compile_obj, accelerators)
444-
linker_libdirs_flags = ['-Wl,-rpath' if l == '-L' else l for l in libdirs_flags]
444+
if self._info['exec'] == 'nvcc':
445+
linker_libdirs_flags = ['-Xcompiler' if l == '-L' else f'"-Wl,-rpath,{l}"' for l in libdirs_flags]
446+
else:
447+
linker_libdirs_flags = ['-Wl,-rpath' if l == '-L' else l for l in libdirs_flags]
445448

446449
flags.insert(0,"-shared")
447450

pyccel/codegen/pipeline.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,10 @@ def handle_error(stage):
179179
if language is None:
180180
language = 'fortran'
181181

182-
# Choose Fortran compiler
182+
# Choose Default compiler
183183
if compiler is None:
184-
compiler = os.environ.get('PYCCEL_DEFAULT_COMPILER', 'GNU')
184+
default_compiler_family = 'nvidia' if language == 'cuda' else 'GNU'
185+
compiler = os.environ.get('PYCCEL_DEFAULT_COMPILER', default_compiler_family)
185186

186187
fflags = [] if fflags is None else fflags.split()
187188
wrapper_flags = [] if wrapper_flags is None else wrapper_flags.split()

pyccel/codegen/printing/cucode.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# coding: utf-8
2+
#------------------------------------------------------------------------------------------#
3+
# This file is part of Pyccel which is released under MIT License. See the LICENSE file or #
4+
# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. #
5+
#------------------------------------------------------------------------------------------#
6+
"""
7+
Provide tools for generating and handling CUDA code.
8+
This module is designed to interface Pyccel's Abstract Syntax Tree (AST) with CUDA,
9+
enabling the direct translation of high-level Pyccel expressions into CUDA code.
10+
"""
11+
12+
from pyccel.codegen.printing.ccode import CCodePrinter, c_library_headers
13+
14+
from pyccel.ast.core import Import, Module
15+
16+
from pyccel.errors.errors import Errors
17+
18+
19+
errors = Errors()
20+
21+
__all__ = ["CudaCodePrinter"]
22+
23+
class CudaCodePrinter(CCodePrinter):
24+
"""
25+
Print code in CUDA format.
26+
27+
This printer converts Pyccel's Abstract Syntax Tree (AST) into strings of CUDA code.
28+
Navigation through this file utilizes _print_X functions,
29+
as is common with all printers.
30+
31+
Parameters
32+
----------
33+
filename : str
34+
The name of the file being pyccelised.
35+
prefix_module : str
36+
A prefix to be added to the name of the module.
37+
"""
38+
language = "cuda"
39+
40+
def __init__(self, filename, prefix_module = None):
41+
42+
errors.set_target(filename, 'file')
43+
44+
super().__init__(filename)
45+
46+
def _print_Module(self, expr):
47+
self.set_scope(expr.scope)
48+
self._current_module = expr.name
49+
body = ''.join(self._print(i) for i in expr.body)
50+
51+
global_variables = ''.join(self._print(d) for d in expr.declarations)
52+
53+
# Print imports last to be sure that all additional_imports have been collected
54+
imports = [Import(expr.name, Module(expr.name,(),())), *self._additional_imports.values()]
55+
c_headers_imports = ''
56+
local_imports = ''
57+
58+
for imp in imports:
59+
if imp.source in c_library_headers:
60+
c_headers_imports += self._print(imp)
61+
else:
62+
local_imports += self._print(imp)
63+
64+
imports = f'{c_headers_imports}\
65+
extern "C"{{\n\
66+
{local_imports}\
67+
}}'
68+
69+
code = f'{imports}\n\
70+
{global_variables}\n\
71+
{body}\n'
72+
73+
self.exit_scope()
74+
return code

pyccel/commands/console.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def pyccel(files=None, mpi=None, openmp=None, openacc=None, output_dir=None, com
8080
# ... backend compiler options
8181
group = parser.add_argument_group('Backend compiler options')
8282

83-
group.add_argument('--language', choices=('fortran', 'c', 'python'), help='Generated language')
83+
group.add_argument('--language', choices=('fortran', 'c', 'python', 'cuda'), help='Generated language')
8484

8585
group.add_argument('--compiler', help='Compiler family or json file containing a compiler description {GNU,intel,PGI}')
8686

0 commit comments

Comments
 (0)