Skip to content

Commit e937806

Browse files
committed
WIP: Merge branch 'master' into gpu
2 parents 54d1214 + a737a31 commit e937806

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+5832
-7207
lines changed

.github/workflows/ci.yml

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,40 +15,82 @@ jobs:
1515
runs-on: ubuntu-latest
1616
env:
1717
CC: mpicc
18-
PETSC_CONFIGURE_OPTIONS: --with-debugging=1
19-
steps:
20-
- name: Checkout repository
21-
uses: actions/checkout@v2
18+
PETSC_DIR: ${{ github.workspace }}/petsc
19+
PETSC_ARCH: default
20+
PETSC_CONFIGURE_OPTIONS: --with-debugging=1 --with-shared-libraries=1 --with-c2html=0 --with-fortran-bindings=0
2221

22+
steps:
2323
- name: Install system dependencies
2424
shell: bash
2525
run: |
26-
sudo apt install \
27-
build-essential python3-dev git python3-pip libopenmpi-dev \
28-
openmpi-bin libblas-dev liblapack-dev gfortran
26+
sudo apt update
27+
sudo apt install build-essential mpich libmpich-dev \
28+
libblas-dev liblapack-dev gfortran
2929
3030
- name: Set correct Python version
3131
uses: actions/setup-python@v2
3232
with:
3333
python-version: '3.6'
3434

35-
# xargs is used to force installation of requirements in the order we specified.
36-
# pip 20.2 needed for loopy install to work.
37-
- name: Install Python dependencies
35+
- name: Clone PETSc
36+
uses: actions/checkout@v2
37+
with:
38+
repository: firedrakeproject/petsc
39+
path: ${{ env.PETSC_DIR }}
40+
41+
- name: Build and install PETSc
3842
shell: bash
43+
working-directory: ${{ env.PETSC_DIR }}
3944
run: |
40-
pip install pip==20.2
41-
xargs -l1 pip install < requirements-ext.txt
42-
xargs -l1 pip install < requirements-git.txt
43-
pip install pulp
44-
pip install -U flake8
45+
./configure ${PETSC_CONFIGURE_OPTIONS}
46+
make
47+
48+
- name: Build and install petsc4py
49+
shell: bash
50+
working-directory: ${{ env.PETSC_DIR }}/src/binding/petsc4py
51+
run: |
52+
python -m pip install --upgrade cython numpy
53+
python -m pip install --no-deps .
54+
55+
- name: Checkout PyOP2
56+
uses: actions/checkout@v2
57+
with:
58+
path: PyOP2
4559

4660
- name: Install PyOP2
4761
shell: bash
48-
run: pip install -e .
62+
working-directory: PyOP2
63+
run: |
64+
python -m pip install pip==20.2 # pip 20.2 needed for loopy install to work.
4965
50-
- name: Do tests
66+
# xargs is used to force installation of requirements in the order we specified.
67+
xargs -l1 python -m pip install < requirements-ext.txt
68+
xargs -l1 python -m pip install < requirements-git.txt
69+
python -m pip install pulp
70+
python -m pip install -U flake8
71+
python -m pip install .
72+
73+
- name: Run linting
5174
shell: bash
75+
working-directory: PyOP2
76+
run: make lint
77+
78+
- name: Run tests
79+
shell: bash
80+
working-directory: PyOP2
81+
run: pytest test -v --tb=native
82+
83+
- name: Build documentation
84+
shell: bash
85+
working-directory: PyOP2
5286
run: |
53-
make lint
54-
py.test test -v --tb=native
87+
python -m pip install sphinx
88+
make -C doc/sphinx html
89+
- name: Upload to github pages
90+
if: ${{ github.ref == 'refs/heads/master' && github.event_name == 'push' }}
91+
uses: crazy-max/[email protected]
92+
with:
93+
build_dir: PyOP2/doc/sphinx/build/html
94+
jekyll: false
95+
env:
96+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/gh-pages.yml

Lines changed: 0 additions & 55 deletions
This file was deleted.

.gitignore

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ PyOP2.egg-info
66
*.py[cdo]
77

88
# Extension modules
9-
computeind.c
10-
computeind.so
11-
sparsity.cpp
129
sparsity.so
13-
10+
sparsity.c
11+
sparsity.cpython*.so
1412
# Docs
1513
pyop2.coffee.rst
1614
pyop2.rst

pyop2/backend.py renamed to pyop2/backends/__init__.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,26 @@ class AbstractComputeBackend:
77
Abstract class to record all the backend specific implementation of
88
:mod:`pyop2`'s data structures.
99
"""
10-
ParLoop = _not_implemented()
11-
Set = _not_implemented()
12-
ExtrudedSet = _not_implemented()
13-
MixedSet = _not_implemented()
14-
Subset = _not_implemented()
15-
DataSet = _not_implemented()
16-
MixedDataSet = _not_implemented()
17-
Map = _not_implemented()
18-
MixedMap = _not_implemented()
19-
Dat = _not_implemented()
20-
MixedDat = _not_implemented()
21-
DatView = _not_implemented()
22-
Mat = _not_implemented()
23-
Global = _not_implemented()
24-
GlobalDataSet = _not_implemented()
10+
ParLoop = _not_implemented
11+
Set = _not_implemented
12+
ExtrudedSet = _not_implemented
13+
MixedSet = _not_implemented
14+
Subset = _not_implemented
15+
DataSet = _not_implemented
16+
MixedDataSet = _not_implemented
17+
Map = _not_implemented
18+
MixedMap = _not_implemented
19+
Dat = _not_implemented
20+
MixedDat = _not_implemented
21+
DatView = _not_implemented
22+
Mat = _not_implemented
23+
Global = _not_implemented
24+
GlobalDataSet = _not_implemented
25+
PETScVecType = _not_implemented
2526

2627
def _getattr_(self, key):
2728
val = super(AbstractComputeBackend, self)._getattr_(key)
28-
if isinstance(val, _not_implemented):
29+
if val is _not_implemented:
2930
raise NotImplementedError("'{}' is not implemented for backend"
3031
" '{}'.".format(val, self.__name__))
3132
return val

pyop2/backends/cpu.py

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
from pyop2.types.dat import Dat as BaseDat, MixedDat, DatView
2+
from pyop2.types.set import Set, ExtrudedSet, Subset, MixedSet
3+
from pyop2.types.dataset import DataSet, GlobalDataSet, MixedDataSet
4+
from pyop2.types.map import Map, MixedMap
5+
from pyop2.parloop import AbstractParLoop, AbstractJITModule
6+
from pyop2.types.mat import Mat
7+
from pyop2.glob import Global
8+
from pyop2.backends import AbstractComputeBackend
9+
from petsc4py import PETSc
10+
from . import (
11+
compilation,
12+
configuration as conf,
13+
datatypes as dtypes,
14+
mpi,
15+
utils
16+
)
17+
18+
import ctypes
19+
import os
20+
import loopy as lp
21+
22+
23+
class Dat(BaseDat):
24+
@utils.cached_property
25+
def _vec(self):
26+
assert self.dtype == PETSc.ScalarType, \
27+
"Can't create Vec with type %s, must be %s" % (self.dtype, PETSc.ScalarType)
28+
# Can't duplicate layout_vec of dataset, because we then
29+
# carry around extra unnecessary data.
30+
# But use getSizes to save an Allreduce in computing the
31+
# global size.
32+
size = self.dataset.layout_vec.getSizes()
33+
data = self._data[:size[0]]
34+
vec = PETSc.Vec().createWithArray(data, size=size, bsize=self.cdim, comm=self.comm)
35+
return vec
36+
37+
38+
class JITModule(AbstractJITModule):
39+
@utils.cached_property
40+
def code_to_compile(self):
41+
from pyop2.codegen.builder import WrapperBuilder
42+
from pyop2.codegen.rep2loopy import generate
43+
44+
builder = WrapperBuilder(kernel=self._kernel,
45+
iterset=self._iterset,
46+
iteration_region=self._iteration_region,
47+
pass_layer_to_kernel=self._pass_layer_arg)
48+
for arg in self._args:
49+
builder.add_argument(arg)
50+
51+
wrapper = generate(builder)
52+
code = lp.generate_code_v2(wrapper)
53+
54+
if self._kernel._cpp:
55+
from loopy.codegen.result import process_preambles
56+
preamble = "".join(process_preambles(getattr(code, "device_preambles", [])))
57+
device_code = "\n\n".join(str(dp.ast) for dp in code.device_programs)
58+
return preamble + "\nextern \"C\" {\n" + device_code + "\n}\n"
59+
return code.device_code()
60+
61+
@PETSc.Log.EventDecorator()
62+
@mpi.collective
63+
def compile(self):
64+
# If we weren't in the cache we /must/ have arguments
65+
if not hasattr(self, '_args'):
66+
raise RuntimeError("JITModule has no args associated with it, should never happen")
67+
68+
compiler = conf.configuration["compiler"]
69+
extension = "cpp" if self._kernel._cpp else "c"
70+
cppargs = self._cppargs
71+
cppargs += ["-I%s/include" % d for d in utils.get_petsc_dir()] + \
72+
["-I%s" % d for d in self._kernel._include_dirs] + \
73+
["-I%s" % os.path.abspath(os.path.dirname(__file__))]
74+
ldargs = ["-L%s/lib" % d for d in utils.get_petsc_dir()] + \
75+
["-Wl,-rpath,%s/lib" % d for d in utils.get_petsc_dir()] + \
76+
["-lpetsc", "-lm"] + self._libraries
77+
ldargs += self._kernel._ldargs
78+
79+
self._fun = compilation.load(self,
80+
extension,
81+
self._wrapper_name,
82+
cppargs=cppargs,
83+
ldargs=ldargs,
84+
restype=ctypes.c_int,
85+
compiler=compiler,
86+
comm=self.comm)
87+
# Blow away everything we don't need any more
88+
del self._args
89+
del self._kernel
90+
del self._iterset
91+
92+
@utils.cached_property
93+
def argtypes(self):
94+
index_type = dtypes.as_ctypes(dtypes.IntType)
95+
argtypes = (index_type, index_type)
96+
argtypes += self._iterset._argtypes_
97+
for arg in self._args:
98+
argtypes += arg._argtypes_
99+
seen = set()
100+
for arg in self._args:
101+
maps = arg.map_tuple
102+
for map_ in maps:
103+
for k, t in zip(map_._kernel_args_, map_._argtypes_):
104+
if k in seen:
105+
continue
106+
argtypes += (t,)
107+
seen.add(k)
108+
return argtypes
109+
...
110+
111+
112+
class ParLoop(AbstractParLoop):
113+
114+
def prepare_arglist(self, iterset, *args):
115+
arglist = iterset._kernel_args_
116+
for arg in args:
117+
arglist += arg._kernel_args_
118+
seen = set()
119+
for arg in args:
120+
maps = arg.map_tuple
121+
for map_ in maps:
122+
if map_ is None:
123+
continue
124+
for k in map_._kernel_args_:
125+
if k in seen:
126+
continue
127+
arglist += (k,)
128+
seen.add(k)
129+
return arglist
130+
131+
@utils.cached_property
132+
def _jitmodule(self):
133+
return JITModule(self.kernel, self.iterset, *self.args,
134+
iterate=self.iteration_region,
135+
pass_layer_arg=self._pass_layer_arg)
136+
137+
@mpi.collective
138+
def _compute(self, part, fun, *arglist):
139+
with self._compute_event:
140+
self.log_flops(part.size * self.num_flops)
141+
fun(part.offset, part.offset + part.size, *arglist)
142+
143+
144+
class CPUBackend(AbstractComputeBackend):
145+
ParLoop = ParLoop
146+
Set = Set
147+
ExtrudedSet = ExtrudedSet
148+
MixedSet = MixedSet
149+
Subset = Subset
150+
DataSet = DataSet
151+
MixedDataSet = MixedDataSet
152+
Map = Map
153+
MixedMap = MixedMap
154+
Dat = Dat
155+
MixedDat = MixedDat
156+
DatView = DatView
157+
Mat = Mat
158+
Global = Global
159+
GlobalDataSet = GlobalDataSet
160+
PETScVecType = 'standard'
161+
162+
def turn_on_offloading(self):
163+
pass
164+
165+
def turn_off_offloading(self):
166+
pass
167+
168+
169+
cpu_backend = CPUBackend()

0 commit comments

Comments
 (0)