diff --git a/integration/.gitignore b/integration/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c585e19389d195ff2268d354ecf676d738a578de --- /dev/null +++ b/integration/.gitignore @@ -0,0 +1 @@ +out \ No newline at end of file diff --git a/integration/CMakeDemo/.gitignore b/integration/CMakeDemo/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..facd9a12fc110d698803cb3e8b6a34b9f00f142c --- /dev/null +++ b/integration/CMakeDemo/.gitignore @@ -0,0 +1 @@ +.cmake \ No newline at end of file diff --git a/integration/CMakeDemo/CMakeLists.txt b/integration/CMakeDemo/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b69ff9aec9fe93af6d5364edb80cff67a51a5ba0 --- /dev/null +++ b/integration/CMakeDemo/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required( VERSION 3.24 ) + +project( pssfg_cmake_integration_test ) + +set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${pssfg_cmake_integration_test_SOURCE_DIR}/.cmake ) + +# Don't try this at home! +file(MAKE_DIRECTORY .cmake) +execute_process( COMMAND sfg-cli cmake make-find-module + WORKING_DIRECTORY ${pssfg_cmake_integration_test_SOURCE_DIR}/.cmake ) + +find_package( PystencilsSfg REQUIRED ) + +set( PystencilsSfg_CONFIG_MODULE codegen_config.py ) + +add_library( genlib ) +pystencilssfg_generate_target_sources( genlib SCRIPTS kernels.py FILE_EXTENSIONS .h .cpp ) +pystencilssfg_generate_target_sources( genlib SCRIPTS more_kernels.py ) diff --git a/integration/CMakeDemo/codegen_config.py b/integration/CMakeDemo/codegen_config.py new file mode 100644 index 0000000000000000000000000000000000000000..8162ae460328ab0229f422c3ec9d63522106a78b --- /dev/null +++ b/integration/CMakeDemo/codegen_config.py @@ -0,0 +1,6 @@ +from pystencilssfg import SfgConfig + + +def configure(cfg: SfgConfig): + cfg.extensions.header = "h++" + cfg.extensions.impl = "c++" diff --git a/integration/CMakeDemo/kernels.py b/integration/CMakeDemo/kernels.py new file mode 100644 index 0000000000000000000000000000000000000000..517c7e0f512761c2cd08842ca5d1a9cd1924edba --- /dev/null +++ b/integration/CMakeDemo/kernels.py @@ -0,0 +1,23 @@ +# type: ignore + +import sympy as sp + +from pystencils import fields, kernel + +from pystencilssfg import SourceFileGenerator, SfgComposer + + +with SourceFileGenerator() as ctx: + sfg = SfgComposer(ctx) + + src, dst = fields("src, dst(1) : double[2D]") + + @kernel + def poisson_jacobi(): + dst[0, 0] @= (src[1, 0] + src[-1, 0] + src[0, 1] + src[0, -1]) / 4 + + poisson_kernel = sfg.kernels.create(poisson_jacobi) + + sfg.function("jacobi_smooth")( + sfg.call(poisson_kernel) + ) diff --git a/integration/CMakeDemo/more_kernels.py b/integration/CMakeDemo/more_kernels.py new file mode 100644 index 0000000000000000000000000000000000000000..5fbd6addccb66596c289ef9abc38b7baf772226b --- /dev/null +++ b/integration/CMakeDemo/more_kernels.py @@ -0,0 +1,24 @@ +# type: ignore + +import sympy as sp + +from pystencils import fields, kernel, Field + +from pystencilssfg import SourceFileGenerator, SfgComposer + +with SourceFileGenerator() as ctx: + sfg = SfgComposer(ctx) + + src: Field = fields("src: double[2D]") + + h = sp.Symbol('h') + + @kernel + def poisson_gs(): + src[0, 0] @= (src[1, 0] + src[-1, 0] + src[0, 1] + src[0, -1]) / 4 + + poisson_kernel = sfg.kernels.create(poisson_gs) + + sfg.function("gs_smooth")( + sfg.call(poisson_kernel) + ) diff --git a/integration/MakeDemo/Makefile b/integration/MakeDemo/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..5a2fb0e99793bf2bcb0665ddc87a8051f48e36f9 --- /dev/null +++ b/integration/MakeDemo/Makefile @@ -0,0 +1,36 @@ + +CXX := clang++ +CXX_FLAGS := -DDEBUG -g -std=c++2b -I/home/fhennig/lssgit/mdspan/include + +PYTHON := python + +MKDIR := mkdir -p +dir_guard = $(MKDIR) $(@D) + +OBJ := obj +BIN := bin +GEN_SRC := generated_src + +.PHONY: all clean + +all: $(BIN)/mdspan_test + +clean: + rm -rf $(BIN) $(OBJ) $(GEN_SRC) + +$(GEN_SRC)/kernels.cpp $(GEN_SRC)/kernels.h &: kernels.py + @$(dir_guard) + $(PYTHON) $< --sfg-output-dir $(@D) + +$(OBJ)/kernels.o: $(GEN_SRC)/kernels.cpp $(GEN_SRC)/kernels.h + @$(dir_guard) + $(CXX) $(CXX_FLAGS) -c -o $@ $< + +$(OBJ)/main.o: main.cpp $(GEN_SRC)/kernels.h + @$(dir_guard) + $(CXX) $(CXX_FLAGS) -c -o $@ $< + +$(BIN)/mdspan_test: $(OBJ)/kernels.o $(OBJ)/main.o + @$(dir_guard) + $(CXX) $(CXX_FLAGS) -o $@ $^ + diff --git a/integration/MakeDemo/kernels.py b/integration/MakeDemo/kernels.py new file mode 100644 index 0000000000000000000000000000000000000000..87f2920b5c788a5031ddbe67a71e788a980183c7 --- /dev/null +++ b/integration/MakeDemo/kernels.py @@ -0,0 +1,39 @@ +# type: ignore + +import sympy as sp + +from pystencils import fields, kernel + +from pystencilssfg import SourceFileGenerator, SfgConfiguration, SfgComposer +from pystencilssfg.lang.cpp import mdspan_ref + +sfg_config = SfgConfiguration( + outer_namespace="make_demo" +) + +with SourceFileGenerator(sfg_config) as ctx: + sfg = SfgComposer(ctx) + + sfg.prelude("""Generated by the pystencils Source File Generator. + +Author: Frederik Hennig <frederik.hennig@fau.de>""") + + sfg.define("using namespace std;") + + sfg.namespace("jacobi") + + u_src, u_dst, f = fields("u_src, u_dst, f : double[2D]", layout="fzyx") + h = sp.Symbol("h") + + @kernel + def poisson_jacobi(): + u_dst[0,0] @= (h**2 * f[0, 0] * u_src[1, 0] + u_src[-1, 0] + u_src[0, 1] + u_src[0, -1]) / 4 + + poisson_kernel = sfg.kernels.create(poisson_jacobi) + + sfg.function("jacobi_smooth")( + sfg.map_field(u_src, mdspan_ref(u_src)), + sfg.map_field(u_dst, mdspan_ref(u_dst)), + sfg.map_field(f, mdspan_ref(f)), + sfg.call(poisson_kernel) + ) diff --git a/integration/MakeDemo/main.cpp b/integration/MakeDemo/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..033261f0f090d0e6ed1bfeec2d999e29a7ac8e90 --- /dev/null +++ b/integration/MakeDemo/main.cpp @@ -0,0 +1,62 @@ +#include <iostream> +#include <fstream> + +#include <cstdint> +#include <vector> + +#include <experimental/mdspan> + +#include "generated_src/kernels.h" + +using field_t = std::mdspan< double, std::extents< uint32_t, std::dynamic_extent, std::dynamic_extent > >; + +double boundary(double x, double y){ + return 1.0; +} + +int main(int argc, char ** argv){ + uint32_t N = 8; /* number of grid nodes */ + double h = 1.0 / (double(N) - 1); + uint32_t n_iters = 100; + + std::vector< double > data_src(N*N); + field_t src(data_src.data(), N, N); + + std::vector< double > data_dst(N*N); + field_t dst(data_dst.data(), N, N); + + std::vector< double > data_f(N*N); + field_t f(data_f.data(), N, N); + + for(uint32_t i = 0; i < N; ++i){ + for(uint32_t j = 0; j < N; ++j){ + if(i == 0 || j == 0 || i == N-1 || j == N-1){ + src[i, j] = boundary(double(i) * h, double(j) * h); + dst[i, j] = boundary(double(i) * h, double(j) * h); + f[i, j] = 0.0; + } + } + } + + for(uint32_t i = 0; i < n_iters; ++i){ + make_demo::jacobi::jacobi_smooth(f, h, dst, src); + std::swap(src, dst); + } + + std::ofstream file("data.out", std::ios::trunc | std::ios::out); + + if(!file.is_open()){ + std::cerr << "Could not open output file.\n"; + } else { + for(uint32_t i = 0; i < N; ++i){ + for(uint32_t j = 0; j < N; ++j){ + file << src[i, j] << " "; + } + file << '\n'; + } + } + + file.close(); + + return 0; +} diff --git a/integration/TestSequencing.py b/integration/TestSequencing.py new file mode 100644 index 0000000000000000000000000000000000000000..b25593a114082ab419de632b48478b0770f079b6 --- /dev/null +++ b/integration/TestSequencing.py @@ -0,0 +1,24 @@ +from pystencilssfg import SourceFileGenerator, SfgComposer + +from lbmpy.advanced_streaming import Timestep +from lbmpy import LBMConfig, create_lb_ast + +with SourceFileGenerator() as ctx: + sfg = SfgComposer(ctx) + + lb_config = LBMConfig(streaming_pattern='esotwist') + + lb_ast_even = create_lb_ast(lbm_config=lb_config, timestep=Timestep.EVEN) + + lb_ast_odd = create_lb_ast(lbm_config=lb_config, timestep=Timestep.ODD) + + kernel_even = sfg.kernels.add(lb_ast_even, "lb_even") + kernel_odd = sfg.kernels.add(lb_ast_odd, "lb_odd") + + sfg.function("myFunction")( + sfg.branch("(timestep & 1) ^ 1")( + sfg.call(kernel_even) + )( + sfg.call(kernel_odd) + ) + ) diff --git a/integration/__init__.py b/integration/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/integration/test_class_composer.py b/integration/test_class_composer.py new file mode 100644 index 0000000000000000000000000000000000000000..2a028b0e48175dc950798006fdf02ace1f408a9a --- /dev/null +++ b/integration/test_class_composer.py @@ -0,0 +1,53 @@ +# type: ignore +from pystencilssfg import SourceFileGenerator, SfgConfiguration, SfgComposer +from pystencilssfg.configuration import SfgCodeStyle +from pystencilssfg.composer import SfgClassComposer + +from pystencils import fields, kernel + +sfg_config = SfgConfiguration( + output_directory="out/test_class_composer", + outer_namespace="gen_code", + codestyle=SfgCodeStyle( + code_style="Mozilla", + force_clang_format=True + ) +) + +f, g = fields("f, g(1): double[2D]") + +with SourceFileGenerator(sfg_config) as ctx: + sfg = SfgComposer(ctx) + + @kernel + def assignments(): + f[0, 0] @= 3 * g[0, 0] + + khandle = sfg.kernels.create(assignments) + + sfg.struct("DataStruct")( + sfg.var("coord", "uint32_t"), + sfg.var("value", "float") + ), + + sfg.klass("MyClass", bases=("MyBaseClass",))( + # class body sequencer + + sfg.constructor(sfg.var("a", "int")) + .init("a_(a)") + .body( + 'cout << "Hi!" << endl;' + ), + + sfg.private( + sfg.var("a_", "int"), + + sfg.method("getX", returns="int")( + "return 2.0;" + ) + ), + + sfg.public( + "using xtype = uint8_t;" + ) + ) diff --git a/integration/test_classes.py b/integration/test_classes.py new file mode 100644 index 0000000000000000000000000000000000000000..4be345197965ae8b15353f3ce0471e265d28b35d --- /dev/null +++ b/integration/test_classes.py @@ -0,0 +1,68 @@ +# type: ignore +from pystencilssfg import SourceFileGenerator, SfgConfiguration, SfgComposer +from pystencilssfg.configuration import SfgCodeStyle +from pystencils.types import PsCustomType +from pystencilssfg.ir.source_components import SfgClass, SfgMemberVariable, SfgConstructor, SfgMethod + +from pystencils import fields, kernel + +sfg_config = SfgConfiguration( + output_directory="out/test_classes", + outer_namespace="gen_code", + codestyle=SfgCodeStyle( + code_style="Mozilla", + force_clang_format=True + ) +) + +f, g = fields("f, g(1): double[2D]") + +with SourceFileGenerator(sfg_config) as ctx: + sfg = SfgComposer(ctx) + + @kernel + def assignments(): + f[0,0] @= 3 * g[0,0] + + khandle = sfg.kernels.create(assignments) + + cls = SfgClass("MyClass") + cls.default.append_member(SfgMethod( + "callKernel", + sfg.call(khandle) + )) + + cls.default.append_member(SfgMethod( + "inlineConst", + sfg.seq( + "return -1.0;" + ), + return_type="double", + inline=True, + const=True + )) + + cls.default.append_member(SfgMethod( + "awesomeMethod", + sfg.seq( + "return 2.0f;" + ), + return_type="float", + inline=False, + const=True + )) + + cls.default.append_member( + SfgMemberVariable( + "stuff", PsCustomType("std::vector< int > &") + ) + ) + + cls.default.append_member( + SfgConstructor( + [sfg.var("stuff", PsCustomType("std::vector< int > &"))], + ["stuff_(stuff)"] + ) + ) + + sfg.context.add_class(cls) diff --git a/integration/test_cuda.py b/integration/test_cuda.py new file mode 100644 index 0000000000000000000000000000000000000000..6b1f1f439c6dc3adbbca73f8a56f676ac9951ef2 --- /dev/null +++ b/integration/test_cuda.py @@ -0,0 +1,16 @@ +from pystencils import Target, CreateKernelConfig, no_jit +from lbmpy import create_lb_update_rule, LBMOptimisation +from pystencilssfg import SourceFileGenerator, SfgConfig + +sfg_config = SfgConfig() +sfg_config.extensions.impl = "cu" +sfg_config.output_directory = "out/test_cuda" +sfg_config.outer_namespace = "gen_code" + +with SourceFileGenerator(sfg_config) as sfg: + gen_config = CreateKernelConfig(target=Target.CUDA, jit=no_jit) + opt = LBMOptimisation(field_layout="fzyx") + update = create_lb_update_rule() + kernel = sfg.kernels.create(update, "lbm_update", gen_config) + + sfg.function("lb_update")(sfg.call(kernel)) diff --git a/integration/test_sycl.py b/integration/test_sycl.py new file mode 100644 index 0000000000000000000000000000000000000000..d49edc71bbf8c10afa57bb7abbe9240043f00c5b --- /dev/null +++ b/integration/test_sycl.py @@ -0,0 +1,21 @@ +from pystencils import Target, CreateKernelConfig, create_kernel, no_jit +from lbmpy import create_lb_update_rule, LBMOptimisation +from pystencilssfg import SourceFileGenerator, SfgConfiguration, SfgOutputMode +from pystencilssfg.lang.cpp import mdspan_ref + +sfg_config = SfgConfiguration( + output_directory="out/test_sycl", + outer_namespace="gen_code", + impl_extension="ipp", + output_mode=SfgOutputMode.INLINE +) + +with SourceFileGenerator(sfg_config) as sfg: + gen_config = CreateKernelConfig(target=Target.SYCL, jit=no_jit) + opt = LBMOptimisation(field_layout="fzyx") + update = create_lb_update_rule() + kernel = sfg.kernels.create(update, "lbm_update", gen_config) + + sfg.function("lb_update")( + sfg.call(kernel) + ) diff --git a/integration/test_sycl_buffer.py b/integration/test_sycl_buffer.py new file mode 100644 index 0000000000000000000000000000000000000000..a1e52eb85af599814a2192b726afd4aae2fd084d --- /dev/null +++ b/integration/test_sycl_buffer.py @@ -0,0 +1,33 @@ +from pystencils import Target, CreateKernelConfig, no_jit +from lbmpy import create_lb_update_rule, LBMOptimisation +from pystencilssfg import SourceFileGenerator, SfgConfig, OutputMode +from pystencilssfg.lang.cpp.sycl_accessor import sycl_accessor_ref +import pystencilssfg.extensions.sycl as sycl +from itertools import chain + +sfg_config = SfgConfig( + output_directory="out/test_sycl_buffer", + outer_namespace="gen_code", + output_mode=OutputMode.INLINE, +) + +with SourceFileGenerator(sfg_config) as sfg: + sfg = sycl.SyclComposer(sfg) + gen_config = CreateKernelConfig(target=Target.SYCL, jit=no_jit) + opt = LBMOptimisation(field_layout="fzyx") + update = create_lb_update_rule(lbm_optimisation=opt) + kernel = sfg.kernels.create(update, "lbm_update", gen_config) + + cgh = sfg.sycl_handler("handler") + rang = sfg.sycl_range(update.method.dim, "range") + mappings = [ + sfg.map_field(field, sycl_accessor_ref(field)) + for field in chain(update.free_fields, update.bound_fields) + ] + + sfg.function("lb_update")( + cgh.parallel_for(rang)( + *mappings, + sfg.call(kernel), + ), + )