Source code for gotranx.codegen.cuda

from __future__ import annotations

from .. import templates
from ..ode import ODE
from .c import Format
from .cpp import CppCodeGenerator, FloatType, GotranCppCodePrinter
from .gpu import GPUIndexingMixin, GPUKernelMixin


[docs] class CUDACodePrinter(GPUIndexingMixin, GotranCppCodePrinter): """The C++ printer for CUDA device code. Math functions are printed without `std::` (`exp(x)`), which resolves to CUDA's device overloads for both float and double. Every integer is printed as a floating point literal: `sqrt(5)` would resolve to the C++ library's constexpr integer overload, which is host-only and cannot be called from a kernel. """ _ns = "" def _print_Integer(self, expr): if self._single_precision: return super()._print_Integer(expr) return f"{int(expr)}.0"
[docs] class CUDACodeGenerator(GPUKernelMixin, CppCodeGenerator): """CUDA kernels: one thread per cell, all cells' states stored state-major. State `i` of cell `cell` is `states[i * n_cells + cell]`, and likewise for the values a kernel writes and for the missing variables; the parameters are shared by every cell. Each kernel takes the number of cells as its last argument. `states` and `values` are not `__restrict__`, so a scheme may update the states in place. """ restrict = "__restrict__" backend_name = "CUDA" def __init__( self, ode: ODE, format: Format = Format.clang_format, remove_unused: bool = False, namespace: str | None = None, float_type: FloatType | str = FloatType.double, ) -> None: super().__init__( ode, format=format, remove_unused=remove_unused, namespace=namespace, float_type=float_type, ) self._printer = CUDACodePrinter(float_type=self.float_type) self._check_reserved_names() @property def template(self): return templates.cuda def _pointer(self, name: str, const: bool = True) -> str: if name == "states": # Not __restrict__: the states may be the values a scheme writes (in place) prefix = "const " if const else "" return f"{prefix}{self.float_type} *{name}" return super()._pointer(name, const=const) def imports(self) -> str: return self._format( "\n".join( ["#pragma once", "#include <cmath>", "#include <cstdint>", "#include <cstring>\n"] ) )