Hi everyone! I am happy to share my final report for Google Summer of Code 2026. Over the past four months, I worked on Brian2CUDA with the goal of making it easier to build, faster to compile, and easier to debug.
In this report, I describe the main problems I worked on, the changes I implemented, the current state of the project, and the work that is still in progress.
Google Summer of Code 2026: Work Product Submission
Organization: INCF, Brian2 Simulator
Project: Fix outstanding issues in Brian2CUDA
Weiyuan Du (@SinYita)
Project Abstract
Brian2CUDA is an extension of the open-source spiking neural network simulator Brian2. It generates C++ and CUDA code, so models written in Brian2’s mathematical notation can run on NVIDIA GPUs. The backend already has strong runtime performance and is used by researchers, but several practical issues made it harder to use and maintain: limited Windows support, slow standalone compilation compared with cpp_standalone and Brian2GeNN, and CUDA-side diagnostics based on unconditional printf and std::cout output.
My work focused on three main goals:
-
Complete Windows support and add cross-platform CI that checks code generation and compilation without a GPU (Issue #225, #320).
-
Reduce standalone compile time by removing Thrust and cuRAND from the public include graph (Issue #179).
-
Add a C++/CUDA logging system that uses Brian2’s console log level, removes unused diagnostics at compile time, and sends host warnings and errors back to Python (Issue #103).
GitHub repository: brian-team/brian2cuda
Mentors: @mstimberg (Marcel Stimberg), @thesamovar (Dan Goodman), @bdevans (Ben Evans)
Project Goals
I organized the project around three user-facing problems:
Phase 1: Windows compatibility
Brian2CUDA did not yet have a complete Windows build path. I aimed to turn the empty win_makefile into a real nmake and nvcc build path, align it with Brian2’s cpp_standalone MSVC support, and add CI that can catch code-generation and compile regressions on both Linux and Windows.
Phase 2: Compilation speed
For a typical model, almost every generated .cu file included objects.h, and objects.h pulled in Thrust, cuRAND, and full network and synapse types. This meant that the compiler paid the same cost many times. I focused on removing Thrust and cuRAND from the public include graph, so most translation units only see std::vector, raw pointers, and named helpers.
Phase 3: CUDA-level logging
Standalone CUDA code printed diagnostics unconditionally. I wanted to reuse Brian2’s existing logger, decide at compile time whether each message should exist, and save host warnings and errors so Python can show them after the standalone process exits.
Work Accomplished
Phase 1: Windows support and platform CI
Brian2CUDA can now generate and compile CUDA standalone projects on Windows with MSVC 2022 and CUDA Toolkit 12.8 or earlier.
-
Replaced the empty win_makefile with a full nmake makefile using separable compilation, nvcc linking, cudart.lib, and curand.lib.
-
Completed the MSVC path in device.py. When cpp_compiler == msvc, Brian2CUDA now generates win_makefile and reuses Brian2’scompile_source(), including vcvars setup.
-
Passed Brian2 cpp_compiler_flags, including /MP, through -Xcompiler on Windows.
-
Added test_platform.py and a GitHub Actions matrix for Ubuntu 24.04 and Windows Server 2022 with CUDA 12.8. The test generates and compiles a small network without requiring a GPU.
Phase 2: Compilation speed
Before this work, a typical code object on master spent about 8–10 seconds in nvcc -dc even when the generated kernel was small. This happened because objects.h exposed Thrust types to every code object.
Original generated declarations:
// Original: every code object had to parse this
extern thrust::host_vector<T> _dynamic_array_foo;
extern thrust::device_vector<T> dev_dynamic_array_foo;
I split this part of the work into stacked pull requests:
-
#332: Slim cuda_utils.h, move cuRAND/RNG support behind rand.h, and include it only where needed. This also needed upstream Brian2 pull request #1852.
-
#333: Use public std::vector and named helpers, then introduce DeviceBuffer PImpl and type erasure so generated objects.cu no longer includes Thrust.
Compile times (examples/mushroombody.py, N=1000, RTX 3080 Ti, CUDA 12.8):
| Version |
make -j12 |
Typical code object |
| master |
33 s |
~8–10 s |
| Thrust isolated |
22 s |
~2–3 s |
| PImpl + type erasure |
12.8 s |
~2–3 s |
Phase 3: CUDA logging
Pull request #338 maps Brian2’s console level to B2C_LOG_LEVEL. B2C_LOG_DEBUG and B2C_LOG_INFO lines are removed by the preprocessor when they are not needed. Host warnings and errors are written to results/cuda_log.txt and then shown again through Brian2’s logger after the standalone process exits.
Contributions During GSoC Period
| Pull request |
Description |
Status |
| #328 |
Windows nmake/nvcc and Linux/Windows compile CI |
Merged |
| #332 |
Slim headers and RNG on demand |
Open |
| #333 |
Thrust isolation and DeviceBuffer PImpl |
Open |
| #338 |
B2C_LOG_* and host WARN/ERROR re-emit |
Open |
| #337 |
Developer handbook |
Open |
| brian2#1852 |
Forward compiler_kwds from BinomialFunction |
Merged |
Current State and Next Steps
Completed work includes the Windows build path, no-GPU compile CI, faster parallel compilation, CUDA logs that follow Brian2’s console level, and developer documentation.
Remaining work starts with landing the stacked pull requests already in review: #332, #333, #337, and #338.
The main follow-up for compilation speed is the ccache branch. Early tests show a large speedup for rebuilds when generated kernels have not changed. The next step is to keep checking cache stability and document when the cache is useful.
Documentation also needs follow-up. Pull request #337, and #338 starts a developer handbook, and the user-facing documentation should describe the current Windows toolchain, including CUDA 12.8 and MSVC 2022, as well as the known CUDA 13 and Visual Studio 2026 limits.
Acknowledgments
I am very grateful to @mstimberg for his careful review and guidance throughout the project, especially on testing and finding the right bottleneck to solve first. I also want to thank @thesamovar, @bdevans, and the Brian community for their feedback, support, and encouragement.
I learned a lot during GSoC, both about Brian2CUDA and about maintaining real scientific software. This project made Brian2CUDA more practical for users and easier to maintain for future development. I plan to keep contributing after GSoC and help finish the remaining pieces. Looking forward to all kinds of guidance or feedbacks from the community and individuals. 