diff --git a/overlay.nix b/overlay.nix index 0093569..8cbd5b8 100644 --- a/overlay.nix +++ b/overlay.nix @@ -51,6 +51,7 @@ let ovniGit = final.ovni.override { useGit = true; }; paraverKernel = callPackage ./pkgs/paraver/kernel.nix { }; pocl = callPackage ./pkgs/pocl/default.nix { }; + pocl-noicd = callPackage ./pkgs/pocl/default.nix { enableICD = false; }; prometheus-slurm-exporter = prev.callPackage ./pkgs/slurm-exporter/default.nix { }; #pscom = callPackage ./pkgs/parastation/pscom.nix { }; # Unmaintaned #psmpi = callPackage ./pkgs/parastation/psmpi.nix { }; # Unmaintaned @@ -98,7 +99,12 @@ let stdenv = final.stdenvClangOmpss2NodesOmpv; }; + ocl-build = callPackage ./test/compilers/opencl.nix { }; + ocl-build-noicd = callPackage ./test/compilers/opencl.nix { ocl-icd = final.pocl-noicd; }; + pocl = callPackage ./test/compilers/pocl.nix { }; + ocl-run-pocl = ocl-build.test-icd; + ocl-run-pocl-noicd = ocl-build-noicd.test-noicd; }; # For now, only build toplevel packages in CI/Hydra diff --git a/pkgs/pocl/default.nix b/pkgs/pocl/default.nix index deded7d..3090eb6 100644 --- a/pkgs/pocl/default.nix +++ b/pkgs/pocl/default.nix @@ -13,6 +13,7 @@ libxml2, # required for statically linked llvm python3, writableTmpDirAsHomeHook, + writeText, fetchFromGitHub, @@ -194,22 +195,20 @@ stdenv.mkDerivation (finalAttrs: { runHook postInstallCheck ''; - setupHook = ./setup-hook.sh; + setupHook = lib.optionalDrvAttr enableICD ( + writeText "setup-hook" '' + addToSearchPath OCL_ICD_VENDORS @out@/etc/OpenCL/vendors + '' + ); passthru = { updateScript = nix-update-script { }; git = finalAttrs.finalPackage.override { useGit = true; }; test = finalAttrs.finalPackage.overrideAttrs { doCheck = true; }; + withICD = enableICD; }; - requiredSystemFeatures = lib.optionals (finalAttrs.finalPackage.doCheck && enableHWLOC) [ - "sys-devices" - ]; - - preCheck = '' - export POCL_DEBUG=error,warn - export NIX_DEBUG=1 - ''; + env.HWLOC_SYNTHETIC = lib.optionalDrvAttr enableHWLOC "node:1 core:1 pu:1"; propagatedBuildInputs = [ stdenv.cc.cc ]; diff --git a/pkgs/pocl/setup-hook.sh b/pkgs/pocl/setup-hook.sh deleted file mode 100644 index 9862975..0000000 --- a/pkgs/pocl/setup-hook.sh +++ /dev/null @@ -1,6 +0,0 @@ -preCheckHooks+=('setupPoclCheck') -preInstallCheckHooks+=('setupPoclCheck') - -setupPoclCheck () { - export OCL_ICD_VENDORS="@out@/etc/OpenCL/vendors" -} diff --git a/test/compilers/opencl.c b/test/compilers/opencl.c new file mode 100644 index 0000000..6066d76 --- /dev/null +++ b/test/compilers/opencl.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include + +#define BUF_LEN 128 + +cl_int exit_err = CL_SUCCESS; + +#define CHECK(cmd) \ + do { \ + cl_int err = cmd; \ + if (err != CL_SUCCESS) { \ + printf("[ERROR] " #cmd " (Error code: %d)\n" \ + "@ "__FILE__ \ + ":%d", \ + err, __LINE__); \ + exit_err = err; \ + goto cleanup; \ + } \ + } while (0) + +const char *kernel_source = "__kernel void vector_add(__global const float *a, " + "__global const float *b, __global float *c) {\n" + " int gid = get_global_id(0);\n" + " c[gid] = a[gid] + b[gid];\n" + "}\n"; + +cl_int test_kernel_compilation(cl_platform_id platform) { + cl_device_id device = NULL; + cl_context context = NULL; + cl_program program = NULL; + cl_int err = CL_SUCCESS; + char device_name[BUF_LEN]; + + // Get first device for this platform + CHECK(clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL)); + + // Get device name + CHECK(clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name), + device_name, NULL)); + printf(" Device: %s\n", device_name); + + context = clCreateContext(NULL, 1, &device, NULL, NULL, &err); + CHECK(err); + + program = clCreateProgramWithSource(context, 1, &kernel_source, NULL, &err); + CHECK(err); + + err = clBuildProgram(program, 1, &device, NULL, NULL, NULL); + if (err != CL_SUCCESS) { + printf(" [ERROR] Kernel compilation failed (Error code: %d)\n", err); + + // Build log + size_t log_size; + CHECK(clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, + &log_size)); + char *log = (char *)malloc(log_size); + CHECK(clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, + log, NULL)); + printf(" Build log:\n%s\n", log); + free(log); + goto cleanup; + } + + printf(" [OK] Kernel compiled successfully!\n"); + +cleanup: + if (program) + clReleaseProgram(program); + if (context) + clReleaseContext(context); + printf("\n"); + + return exit_err; +} + +int main() { + cl_uint num_platforms; + cl_platform_id *platforms = NULL; + + // Get number of platforms + CHECK(clGetPlatformIDs(0, NULL, &num_platforms)); + + printf("Found %d OpenCL platform(s)\n\n", num_platforms); + + if (num_platforms == 0) { + printf("No OpenCL platforms found!\n"); + return EXIT_FAILURE; + } + + // Allocate memory for platforms + platforms = (cl_platform_id *)malloc(sizeof(cl_platform_id) * num_platforms); + + // Get platform IDs + CHECK(clGetPlatformIDs(num_platforms, platforms, NULL)); + + // Query each platform and test kernel compilation + for (cl_uint i = 0; i < num_platforms; i++) { + char platform_name[BUF_LEN]; + char platform_vendor[BUF_LEN]; + char platform_version[BUF_LEN]; + + CHECK(clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, + sizeof(platform_name), platform_name, NULL)); + CHECK(clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, + sizeof(platform_vendor), platform_vendor, NULL)); + CHECK(clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, + sizeof(platform_version), platform_version, NULL)); + + printf("Platform %d: %s\n", i, platform_name); + printf(" Vendor: %s\n", platform_vendor); + printf(" Version: %s\n", platform_version); + + // Test kernel compilation + CHECK(test_kernel_compilation(platforms[i])); + } + +cleanup: + if (platforms) + free(platforms); + + if (exit_err == CL_SUCCESS) + return EXIT_SUCCESS; + + return EXIT_FAILURE; +} diff --git a/test/compilers/opencl.nix b/test/compilers/opencl.nix new file mode 100644 index 0000000..ac7bcfd --- /dev/null +++ b/test/compilers/opencl.nix @@ -0,0 +1,101 @@ +{ + stdenv, + ocl-icd, + opencl-headers, + pocl, + clinfo, + writableTmpDirAsHomeHook, + runCommand, + lib, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "opencl-pocl-test"; + version = "1.0.0"; + + src = ./opencl.c; + + dontUnpack = true; + dontConfigure = true; + + buildInputs = [ + ocl-icd + opencl-headers + ]; + + buildPhase = '' + runHook preBuild + + $CC -Wall -Wextra -D CL_TARGET_OPENCL_VERSION=100 $src -o ocl-hello -lOpenCL + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + cp ocl-hello $out/bin + + runHook postInstall + ''; + + passthru = { + test-icd = + runCommand "custom-clinfo" + { + nativeBuildInputs = + assert !(lib.hasPrefix "pocl" ocl-icd.pname); + [ + clinfo + finalAttrs.finalPackage + pocl + writableTmpDirAsHomeHook + ]; + + env.POCL_DEBUG = "error,warn"; + + requiredSystemFeatures = [ "sys-devices" ]; + } + + '' + set -x + + mkdir $out + + clinfo -l >$out/clinfo + clinfo >$out/clinfo-full + + ocl-hello >$out/hello + + for i in $out/*; do + grep "Portable Computing Language" $i + done + + echo $OCL_ICD_VENDORS >$out/env + + grep "pocl.*/etc/OpenCL/vendors" $out/env + + set +x + ''; + # this needs: ocl-icd = pocl-noicd + test-noicd = + runCommand "custom-clinfo" + { + nativeBuildInputs = [ + finalAttrs.finalPackage + writableTmpDirAsHomeHook + ]; + + env.POCL_DEBUG = "error,warn"; + + requiredSystemFeatures = [ "sys-devices" ]; + } + + '' + ocl-hello >$out + + grep "Portable Computing Language" $out + ''; + }; +}) diff --git a/test/compilers/pocl.nix b/test/compilers/pocl.nix index 054949a..eb6b979 100644 --- a/test/compilers/pocl.nix +++ b/test/compilers/pocl.nix @@ -9,18 +9,18 @@ runCommand "clinfo-pocl" { nativeBuildInputs = [ clinfo + pocl writableTmpDirAsHomeHook ]; requiredSystemFeatures = [ "sys-devices" ]; - env = { - POCL_DEBUG = "error,warn"; - OCL_ICD_VENDORS = "${pocl}/etc/OpenCL/vendors"; - }; + env.POCL_DEBUG = "error,warn"; } '' - set -x - clinfo | tee $out - set +x + echo $OCL_ICD_VENDORS + clinfo >$out + + # check that we have PoCL: + grep "Portable Computing Language" $out ''