Skip to content
Snippets Groups Projects

Add custom opencl

Merged EXT Jean-Matthieu Etancelin requested to merge add-custom-opencl into master
1 file
+ 0
2
Compare changes
  • Side-by-side
  • Inline
+ 179
0
"""Test custom operator."""
from hysop.constants import HYSOP_REAL
from hysop.testsenv import __ENABLE_LONG_TESTS__, __HAS_OPENCL_BACKEND__
from hysop.testsenv import opencl_failed, iter_clenv
from hysop.tools.contexts import printoptions
from hysop.tools.types import check_instance, first_not_None
from hysop.tools.numpywrappers import npw
from hysop.tools.io_utils import IO
from hysop import Field, Box
from hysop.operators import CustomOperator
from hysop.constants import Implementation
class TestCustom(object):
@classmethod
def setup_class(cls,
enable_extra_tests=__ENABLE_LONG_TESTS__,
enable_debug_mode=False):
IO.set_default_path('/tmp/hysop_tests/test_custom')
if enable_debug_mode:
cls.size_min = 15
cls.size_max = 16
else:
cls.size_min = 23
cls.size_max = 87
cls.enable_extra_tests = enable_extra_tests
cls.enable_debug_mode = enable_debug_mode
@classmethod
def teardown_class(cls):
pass
def perform_tests(self):
self._test(dim=3, dtype=HYSOP_REAL)
@staticmethod
def __analytic_init(data, coords, component):
(x, y, z) = coords
data[...] = (x**2)*npw.sin(y)*npw.exp(z)
for _ in range(1, 6):
data[...] += (x**2)*npw.sin(y)*npw.exp(z*_)
@staticmethod
def __analytic_python(F):
TestCustom.__analytic_init(F.data[0], F.compute_mesh_coords, 0)
__analytic_opencl = """
int3 i_xyz = get_Fi_xyz(i);
double3 xyz = (double3)(F_mesh.local_mesh.xmin.x+i_xyz.x*F_mesh.dx.x,
F_mesh.local_mesh.xmin.y+i_xyz.y*F_mesh.dx.y,
F_mesh.local_mesh.xmin.z+i_xyz.z*F_mesh.dx.z);
double Fi = xyz.x*xyz.x*sin(xyz.y)*exp(xyz.z);
for(int k=1; k<6;k++) Fi += xyz.x*xyz.x*sin(xyz.y)*exp(xyz.z*k);
F[i] = Fi;
"""
def _test(self, dim, dtype,
size_min=None, size_max=None):
enable_extra_tests = self.enable_extra_tests
size_min = first_not_None(size_min, self.size_min)
size_max = first_not_None(size_max, self.size_max)
shape = tuple(npw.random.randint(low=size_min, high=size_max+1, size=dim).tolist())
domain = Box(length=(1,)*dim)
F = Field(domain=domain, name='F', dtype=dtype,
nb_components=1)
print(' >Testing all implementations:')
implementations = CustomOperator.implementations()
variables = {F: shape}
def iter_impl(impl):
base_kwds = dict(invars=(), outvars=(F,),
variables=variables,
implementation=impl,
name='custom_{}'.format(str(impl).lower()))
if impl is Implementation.PYTHON:
msg = ' *Python: '
print(msg, end=' ')
yield CustomOperator(func=self.__analytic_python, **base_kwds)
print()
elif impl is Implementation.OPENCL:
msg = ' *OpenCL: '
print(msg)
for cl_env in iter_clenv():
print(' *platform {}, device {}: '.format(cl_env.platform.name.strip(),
cl_env.device.name.strip()), end=' ')
yield CustomOperator(cl_env=cl_env,
func=self.__analytic_opencl, **base_kwds)
print()
else:
msg = 'Unknown implementation to test {}.'.format(impl)
raise NotImplementedError(msg)
print('\nTesting {}D Custom Operator: dtype={} shape={}'.format(
dim, dtype.__name__, shape))
Fref = None
for impl in implementations:
for op in iter_impl(impl):
op = op.build()
dF = op.get_output_discrete_field(F)
if (Fref is None):
dF.initialize(self.__analytic_init)
Fref = tuple(data.get().handle.copy() for data in dF.data)
op.apply()
Fout = tuple(data.get().handle.copy() for data in dF.data)
self._check_output(impl, op, Fref, Fout)
@classmethod
def _check_output(cls, impl, op, Fref, Fout):
check_instance(Fref, tuple, values=npw.ndarray)
check_instance(Fout, tuple, values=npw.ndarray, size=len(Fref))
msg0 = 'Reference field {} is not finite.'
for (i, field) in enumerate(Fref):
iname = 'F{}'.format(i)
mask = npw.isfinite(field)
if not mask.all():
print()
print(field)
print()
print(field[~mask])
print()
msg = msg0.format(iname)
raise ValueError(msg)
for i, (fout, fref) in enumerate(zip(Fout, Fref)):
iname = '{}{}'.format('F', i)
assert fout.dtype == fref.dtype, iname
assert fout.shape == fref.shape, iname
eps = npw.finfo(fout.dtype).eps
dist = npw.abs(fout-fref)
dinf = npw.max(dist)
deps = int(npw.ceil(dinf/eps))
if (deps < 1000):
print('{}eps, '.format(deps), end=' ')
continue
has_nan = npw.any(npw.isnan(fout))
has_inf = npw.any(npw.isinf(fout))
print()
print()
print('Test output comparisson for {} failed for component {}:'.format(iname, i))
print(' *has_nan: {}'.format(has_nan))
print(' *has_inf: {}'.format(has_inf))
print(' *dinf={} ({} eps)'.format(dinf, deps))
print()
msg = 'Test failed for {} on component {} for implementation {}.'.format(iname, i, impl)
raise RuntimeError(msg)
def test(self):
self._test(3, HYSOP_REAL)
def perform_tests(self):
self.test()
if __name__ == '__main__':
TestCustom.setup_class(enable_extra_tests=False,
enable_debug_mode=False)
test = TestCustom()
with printoptions(threshold=10000, linewidth=240,
nanstr='nan', infstr='inf',
formatter={'float': lambda x: '{:>6.2f}'.format(x)}):
test.perform_tests()
TestCustom.teardown_class()
Loading