From 17fb33eddd613c0e14b061a5195e2ea6c90ee9d4 Mon Sep 17 00:00:00 2001 From: v1kko Date: Mon, 1 Jun 2026 09:32:11 +0000 Subject: [PATCH 1/4] Add 'make test' target to build and run correctness tests Add a top-level `test` target that builds the library and the test programs against it, then runs the GPU-vs-CPU correctness tests for the 4th-order, GRAPE5 (2nd-order) and 6th-order integrators. The target dispatches to the CUDA or OpenCL test Makefile based on the selected BACKEND, and sets LD_LIBRARY_PATH so the freshly built shared libraries are found at runtime. A `build-tests` target is also provided to compile the tests without running them, and `clean` now also cleans the tests directory. Fix two pre-existing bugs in tests/Makefile_ocl that prevented the OpenCL tests from building/running: link against libsapporo2 (not the old libsapporo name) and symlink kernels from src/OpenCL. Co-Authored-By: Claude Opus 4.8 --- Makefile | 31 +++++++++++++++++++++++++++++++ tests/Makefile_ocl | 4 ++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 1925282..b354dac 100644 --- a/Makefile +++ b/Makefile @@ -215,9 +215,40 @@ uninstall: rm -rf $(INSTALLED_LIBS) $(INSTALLED_HEADERS) +# Tests +# Build the test programs against the freshly built libraries and run the +# GPU-vs-CPU correctness tests for each supported integration order. The +# backend selected above determines which test Makefile and binaries are used. +ifeq ($(BACKEND), CUDA) + TEST_MAKEFILE := Makefile + TEST_SUFFIX := cuda +else + TEST_MAKEFILE := Makefile_ocl + TEST_SUFFIX := ocl +endif + +CORRECTNESS_TESTS := test_gravity_block_$(TEST_SUFFIX) \ + test_gravity_block_g5_$(TEST_SUFFIX) \ + test_gravity_block_6th_$(TEST_SUFFIX) + +.PHONY: build-tests +build-tests: all + $(MAKE) -C tests -f $(TEST_MAKEFILE) CXX="$(CXX)" CC="$(CC)" \ + $(if $(CUDA_TK),CUDA_TK="$(CUDA_TK)") + +.PHONY: test +test: build-tests + @for t in $(CORRECTNESS_TESTS); do \ + echo "=== Running $$t ==="; \ + ( cd tests && LD_LIBRARY_PATH="$(CURDIR):$$LD_LIBRARY_PATH" ./$$t ) || exit 1; \ + done + + # Clean-up .PHONY: clean clean: rm -f *.a *.so src/*.o src/SSE_AVX/SSE/*.o src/SSE_AVX/AVX/*.o rm -f src/CUDA/*.ptx src/CUDA/*.ptxh src/OpenCL/*.cle src/OpenCL/*.clh + $(MAKE) -C tests -f Makefile clean + $(MAKE) -C tests -f Makefile_ocl clean diff --git a/tests/Makefile_ocl b/tests/Makefile_ocl index 11ea0c1..5d5c106 100644 --- a/tests/Makefile_ocl +++ b/tests/Makefile_ocl @@ -3,7 +3,7 @@ CXX ?= g++ .SUFFIXES: .o .cpp .ptx .cu SAPPOROPATH=.. -SAPLIB2 = sapporo +SAPLIB2 = sapporo2 SAPLIB = lib$(SAPLIB2).a SAPLIBG6 = sapporoG6 @@ -28,7 +28,7 @@ PROG = test_gravity_block_ocl test_gravity_block_6th_ocl test_performance_rangeN all: $(OBJ) $(PROG) kernels kernels: - rm -f OpenCL && ln -s $(SAPPOROPATH)/OpenCL OpenCL + rm -f OpenCL && ln -s $(SAPPOROPATH)/src/OpenCL OpenCL test_gravity_block_ocl : test_gravity_block_ocl.o $(CXX) $(LDFLAGS) $^ -o $@ -L $(SAPPOROPATH) -l$(SAPLIB2) $(LDFLAGS) From c1adf9dc0cc418062f5a4f0c81297abf2574de61 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Thu, 4 Jun 2026 17:39:40 +0200 Subject: [PATCH 2/4] Try to get an NVIDIA GPU if available --- src/ocldev.h | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/ocldev.h b/src/ocldev.h index 68ea286..4a5b552 100644 --- a/src/ocldev.h +++ b/src/ocldev.h @@ -257,14 +257,29 @@ namespace dev { oclSafeCall(clGetPlatformInfo(PlatformIDs[dev], CL_PLATFORM_NAME, sizeof(platform_string), &platform_string, NULL)); std::cerr << " " << dev << ": " << platform_string << "\n"; } - fprintf(stderr, "Using platform %d \n", platform_id); - PlatformID = PlatformIDs[platform_id]; + + // Prefer NVIDIA platform if available. + int selected_platform = platform_id; + if (platform_id == 0 && numPlatforms > 1) { + for (cl_uint p = 0; p < numPlatforms; p++) { + char platform_string[1024]; + oclSafeCall(clGetPlatformInfo(PlatformIDs[p], CL_PLATFORM_NAME, sizeof(platform_string), &platform_string, NULL)); + if (strstr(platform_string, "NVIDIA") != NULL) { + std::cerr << "Found NVIDIA platform at index " << p << ", preferring it over others.\n"; + selected_platform = p; + break; + } + } + } + + fprintf(stderr, "Using platform %d \n", selected_platform); + PlatformID = PlatformIDs[selected_platform]; oclSafeCall(clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount)); Devices.resize(DeviceCount); oclSafeCall(clGetDeviceIDs(PlatformID, DeviceType, DeviceCount, &Devices[0], &DeviceCount)); - + std::cerr << "Found " << DeviceCount << " suitable devices: \n"; for (cl_uint dev = 0; dev < DeviceCount; dev++) { char device_string[1024]; From b2382a9ab4eb8b0b0b6e1bb7e7e6940dc9f2bde9 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Thu, 4 Jun 2026 18:11:13 +0200 Subject: [PATCH 3/4] This is a safety net when no GPU is available --- src/ocldev.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ocldev.h b/src/ocldev.h index 4a5b552..0c8d518 100644 --- a/src/ocldev.h +++ b/src/ocldev.h @@ -275,7 +275,15 @@ namespace dev { fprintf(stderr, "Using platform %d \n", selected_platform); PlatformID = PlatformIDs[selected_platform]; - oclSafeCall(clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount)); + // Try to get devices of the requested type. If none are found for GPU, + // fall back to CPU devices (useful when using pocl or CPU-only runtimes). + cl_int ciErrNum = clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount); + if (ciErrNum == CL_DEVICE_NOT_FOUND && DeviceType == CL_DEVICE_TYPE_GPU) { + std::cerr << "No GPU devices found on platform, trying CPU devices...\n"; + DeviceType = CL_DEVICE_TYPE_CPU; + ciErrNum = clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount); + } + oclSafeCall(ciErrNum); Devices.resize(DeviceCount); oclSafeCall(clGetDeviceIDs(PlatformID, DeviceType, DeviceCount, &Devices[0], &DeviceCount)); From 587e31b3e162084d30822010ca15064ab1876b64 Mon Sep 17 00:00:00 2001 From: Hanno Spreeuw Date: Thu, 4 Jun 2026 18:26:36 +0200 Subject: [PATCH 4/4] Revert "This is a safety net when no GPU is available" This reverts commit b2382a9ab4eb8b0b0b6e1bb7e7e6940dc9f2bde9. --- src/ocldev.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ocldev.h b/src/ocldev.h index 0c8d518..4a5b552 100644 --- a/src/ocldev.h +++ b/src/ocldev.h @@ -275,15 +275,7 @@ namespace dev { fprintf(stderr, "Using platform %d \n", selected_platform); PlatformID = PlatformIDs[selected_platform]; - // Try to get devices of the requested type. If none are found for GPU, - // fall back to CPU devices (useful when using pocl or CPU-only runtimes). - cl_int ciErrNum = clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount); - if (ciErrNum == CL_DEVICE_NOT_FOUND && DeviceType == CL_DEVICE_TYPE_GPU) { - std::cerr << "No GPU devices found on platform, trying CPU devices...\n"; - DeviceType = CL_DEVICE_TYPE_CPU; - ciErrNum = clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount); - } - oclSafeCall(ciErrNum); + oclSafeCall(clGetDeviceIDs(PlatformID, DeviceType, 0, NULL, &DeviceCount)); Devices.resize(DeviceCount); oclSafeCall(clGetDeviceIDs(PlatformID, DeviceType, DeviceCount, &Devices[0], &DeviceCount));