diff --git a/pystencils/backends/opencl_backend.py b/pystencils/backends/opencl_backend.py index d2e40a69f05fe1181fc41110ca9a1b07763a75be..4217e9384644d86db7c225c0bd092c9fac7f1558 100644 --- a/pystencils/backends/opencl_backend.py +++ b/pystencils/backends/opencl_backend.py @@ -81,7 +81,10 @@ class OpenClSympyPrinter(CudaSympyPrinter): # For math functions, OpenCL is more similar to the C++ printer CustomSympyPrinter # since built-in math functions are generic. # In CUDA, you have to differentiate between `sin` and `sinf` - _print_math_func = CustomSympyPrinter._print_math_func + try: + _print_math_func = CustomSympyPrinter._print_math_func + except AttributeError: + pass _print_Pow = CustomSympyPrinter._print_Pow def _print_Function(self, expr): diff --git a/pystencils/opencl/opencljit.py b/pystencils/opencl/opencljit.py index 75076db53bd8dd37457fc4bb9c9dea833942d57f..f1df02936b035d178eed91f1c4ed2fd05a31e44c 100644 --- a/pystencils/opencl/opencljit.py +++ b/pystencils/opencl/opencljit.py @@ -41,8 +41,12 @@ def make_python_function(kernel_function_node, opencl_queue, opencl_ctx, argumen code += str(generate_c(kernel_function_node, dialect='opencl', custom_backend=custom_backend)) options = [] if USE_FAST_MATH: - options.append("-cl-unsafe-math-optimizations -cl-mad-enable -cl-fast-relaxed-math -cl-finite-math-only") - options.append("-I \"" + get_pystencils_include_path() + "\"") + options.append("-cl-unsafe-math-optimizations") + options.append("-cl-mad-enable") + options.append("-cl-fast-relaxed-math") + options.append("-cl-finite-math-only") + options.append("-I") + options.append(get_pystencils_include_path()) mod = cl.Program(opencl_ctx, code).build(options=options) func = getattr(mod, kernel_function_node.function_name) diff --git a/pystencils/transformations.py b/pystencils/transformations.py index c790995a31b9a3906427f40a0b4d8795d7469647..48e22a4f74a3de1f9a6e50242016b00b87d6f6a1 100644 --- a/pystencils/transformations.py +++ b/pystencils/transformations.py @@ -1315,13 +1315,16 @@ def implement_interpolations(ast_node: ast.Node, substitutions = {i: to_texture_map[i.symbol.interpolator].at( [o for o in i.offsets]) for i in interpolation_accesses} - import pycuda.driver as cuda - for texture in substitutions.values(): - if can_use_hw_interpolation(texture): - texture.filter_mode = cuda.filter_mode.LINEAR - else: - texture.filter_mode = cuda.filter_mode.POINT - texture.read_as_integer = True + try: + import pycuda.driver as cuda + for texture in substitutions.values(): + if can_use_hw_interpolation(texture): + texture.filter_mode = cuda.filter_mode.LINEAR + else: + texture.filter_mode = cuda.filter_mode.POINT + texture.read_as_integer = True + except Exception: + pass if isinstance(ast_node, AssignmentCollection): ast_node = ast_node.subs(substitutions) diff --git a/pystencils_tests/test_opencl.py b/pystencils_tests/test_opencl.py index 24ef56f9b5e868496d4240d33fe708aaf82b43ed..adffeb4750a62f5bb08ded29fffe00ac5900f706 100644 --- a/pystencils_tests/test_opencl.py +++ b/pystencils_tests/test_opencl.py @@ -1,8 +1,8 @@ import numpy as np import pytest -import sympy as sp import pystencils +import sympy as sp from pystencils.backends.cuda_backend import CudaBackend from pystencils.backends.opencl_backend import OpenClBackend from pystencils.opencl.opencljit import make_python_function @@ -40,6 +40,8 @@ def test_print_opencl(): @pytest.mark.skipif(not HAS_OPENCL, reason="Test requires pyopencl") def test_opencl_jit_fixed_size(): + pytest.importorskip('pycuda') + z, y, x = pystencils.fields("z, y, x: [20,30]") assignments = pystencils.AssignmentCollection({ @@ -92,6 +94,8 @@ def test_opencl_jit_fixed_size(): @pytest.mark.skipif(not HAS_OPENCL, reason="Test requires pyopencl") def test_opencl_jit(): + pytest.importorskip('pycuda') + z, y, x = pystencils.fields("z, y, x: [2d]") assignments = pystencils.AssignmentCollection({ @@ -144,6 +148,8 @@ def test_opencl_jit(): @pytest.mark.skipif(not HAS_OPENCL, reason="Test requires pyopencl") def test_opencl_jit_with_parameter(): + pytest.importorskip('pycuda') + z, y, x = pystencils.fields("z, y, x: [2d]") a = sp.Symbol('a') @@ -195,5 +201,35 @@ def test_opencl_jit_with_parameter(): assert np.allclose(result_cuda, result_opencl) -if __name__ == '__main__': - test_opencl_jit() +@pytest.mark.skipif(not HAS_OPENCL, reason="Test requires pyopencl") +def test_without_cuda(): + z, y, x = pystencils.fields("z, y, x: [20,30]") + + assignments = pystencils.AssignmentCollection({ + z[0, 0]: x[0, 0] * sp.log(x[0, 0] * y[0, 0]) + }) + + print(assignments) + + ast = pystencils.create_kernel(assignments, target='gpu') + + print(ast) + + opencl_code = pystencils.show_code(ast, custom_backend=OpenClBackend()) + print(opencl_code) + + x_cpu = np.random.rand(20, 30) + y_cpu = np.random.rand(20, 30) + z_cpu = np.random.rand(20, 30) + + import pyopencl.array as array + ctx = cl.create_some_context(0) + queue = cl.CommandQueue(ctx) + + x = array.to_device(queue, x_cpu) + y = array.to_device(queue, y_cpu) + z = array.to_device(queue, z_cpu) + + opencl_kernel = make_python_function(ast, queue, ctx) + assert opencl_kernel is not None + opencl_kernel(x=x, y=y, z=z)