stdgpu: STL-shaped containers that live in GPU memory
stdgpu: Efficient STL-like Data Structures on the GPU
At a glance
- What is it?
- stdgpu is a C++17 library that puts standard containers on the device, with unordered_set, unordered_map, vector, deque, queue, stack, bitset and atomic types, and it can run the same code on CUDA, OpenMP or HIP backends.
- Who is it for?
- stdgpu fits a project doing real data management on the device, where the bottleneck is set membership or a hash lookup rather than arithmetic, and where you want container semantics rather than a raw memory pool. It is a poor fit for a numeric kernel that thrust or ArrayFire already covers, since stdgpu is deliberately orthogonal to those, and a poor fit if you need HIP, because that backend is experimental.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 56 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- stotko/stdgpu1,274 ★ · +2
| Repository | 2026-10-21 | 2026-11-07 |
|---|---|---|
| stotko/stdgpu | 1.3k | 1.3k |
2 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Containers on the device, and the deliberate gap with thrust
stdgpu is an open-source library providing generic GPU data structures for fast and reliable data management, and the positioning in the README is unusually clear about what it is not.
The project describes itself as a lightweight C++17 library with minimal dependencies, with CUDA, OpenMP and HIP, experimental, backends, offering familiar STL-like GPU containers, high-level agnostic container functions like insert(begin, end) so you can write shared C++ code, and low-level native container functions like find(key) so you can write custom CUDA kernels. It also interoperates with thrust GPU algorithms.
The framing paragraph is the part to read, because it explains the whole design. Instead of providing yet another ecosystem, stdgpu is designed to be a lightweight container library. Previous libraries such as thrust, VexCL, ArrayFire or Boost.Compute focus on the fast and efficient implementation of various algorithms and only operate on contiguously stored data. stdgpu follows an orthogonal approach and focuses on fast and reliable data management, to enable the rapid development of more general and flexible GPU algorithms just like their CPU counterparts.
So the division of labour with thrust is: thrust for algorithms over contiguous arrays, stdgpu for the data structures when the data is not contiguous. That is a real niche, and a meaningful one, because a hash set on the device is not something thrust provides.
The container list covers the usual suspects. atomic and atomic_ref for atomic primitive types and references, bitset as a space-efficient bit array, deque as a dynamically sized double-ended queue, queue and stack as container adapters, unordered_map and unordered_set as hashed collections of unique keys and key-value pairs, and vector as a dynamically sized contiguous array.
Around the containers is a set of helper groups that mirror the standard library headers: algorithm, bit, contract, cstddef, execution, functional, iterator, limits, memory, mutex, numeric, ranges, type_traits and utility. The project is Apache-2.0 licensed, the last push was on 2026-09-12, and the releases are 1.3.0 from 2020-06-02, 1.2.0 from 2020-01-28 and 1.1.0 from 2019-11-22.
Agnostic code and native code, and how they compose
The library is built so that the same algorithm can be written in two styles, and the examples directory shows the intent: examples/contract.cpp, examples/createAndDestroyDeviceArray.cpp, examples/createAndDestroyDeviceObject.cpp, and separate example directories for cuda, hip and openmp.
The agnostic style is where you use the container through a generic interface, typically with thrust algorithms. The example in the README is a stream_set class that keeps a duplicate-free set of blocks:
#include <stdgpu/cstddef.h> // stdgpu::index_t
#include <stdgpu/iterator.h> // stdgpu::make_device
#include <stdgpu/unordered_set.cuh> // stdgpu::unordered_set
class stream_set
{
public:
void
add_blocks(const short3* blocks,
const stdgpu::index_t n)
{
set.insert(stdgpu::make_device(blocks),
stdgpu::make_device(blocks + n));
}
// Further functions
private:
stdgpu::unordered_set<short3> set;
// Further members
};The detail that makes this work is stdgpu::make_device, which takes a host pointer and an index count and produces the device-side view the container expects, and the set itself lives in device memory as a member of the class.
The native style is for the operations that a generic interface cannot express, the README gives the creation of the duplicate-free set of updated blocks as the example of something implemented in custom CUDA kernels with the CUDA backend enabled. So the division is: use the agnostic path where thrust or another generic algorithm can do the work, drop to native kernels where the operation is specific to the container.
The real-world reference in the documentation is SLAMCast, a scalable live telepresence system, where stdgpu is used for real-time large-scale 3D scene reconstruction and for streaming 3D data between a server and remote clients. The add_blocks example above is drawn from that context, and the word streamed is what makes the container choice obvious: a queue of blocks that arrives out of order and has to be deduplicated is a set membership problem, and doing it on the host would mean a round trip per block.
Three backends, and one that is still experimental
The backend story is the practical part of the library, because the containers have to run wherever your kernels run.
CUDA is the primary target, and the container implementations carry the .cuh suffix, which is the CUDA convention for a header with device code in it. The example above includes stdgpu/unordered_set.cuh, and the README describes writing custom kernels with the CUDA backend enabled.
OpenMP is the second backend, and it is the one that makes the library useful outside the NVIDIA ecosystem. The CI badges are telling here, since there are two separate workflows, tests.yml labelled Tests OpenMP and lint.yml labelled Lint OpenMP, so the OpenMP path is tested and linted in its own right. An OpenMP backend is what lets the same container code run on a CPU with threads, which is how you develop and test GPU code without a GPU, and it also means the library is usable on a machine where the accelerator is an AMD GPU via the third backend.
HIP is the third, and it is marked experimental in the feature list. HIP is AMD's equivalent of CUDA, so a HIP backend is what would let this code run on an AMD accelerator, and the fact that it is experimental is the single most important qualifier in the feature list. The examples directory has a hip/ subdirectory alongside cuda/ and openmp/, so the support is being worked on, but the label in the feature bullet is the authoritative statement.
The topic tags reflect the same spread: cpp, cpp17, cpp20, cuda, hip, rocm, openmp, gpgpu, gpu, gpu-acceleration and gpu-computing.
The project also carries the Core Infrastructure Initiative best practices badge, and there is a codecov badge for coverage, so the containers are covered by tests and the project follows a recognised set of open source practices.
The helper groups, and why the contract group exists
The container list is the headline, but the set of helper groups around it is what makes the library usable, and one of those groups is worth singling out.
The helpers are named after the standard library headers they mirror: algorithm, bit, contract, cstddef, execution, functional, iterator, limits, memory, mutex, numeric, ranges, type_traits and utility. The point of mirroring the standard library naming is that a reader who knows std::vector knows where to look, and a piece of portable-looking code that includes a stdgpu header has an obvious GPU counterpart.
The contract group is the unusual one. Contract checking is a way of specifying preconditions and postconditions on a function, and its presence in a GPU library makes sense for a reason that is specific to this domain: on a device, a precondition failure does not throw an exception, it corrupts memory or hangs the kernel. A contract violation in a CUDA kernel is a much nastier debugging experience than an assertion in host code, so making the conditions explicit and checkable at the point where the data structure is used is a real engineering need rather than a stylistic preference.
The mutex group is the other one with a GPU-specific reason. On the device, a mutex cannot be a host thread mutex, so the group has to provide something that works with the execution model of the backend in use, which for OpenMP is a different thing than for CUDA.
The memory group and the iterator group are where the host-to-device boundary lives. The stdgpu::make_device call in the README example is from the iterator group, and it is the piece that turns a host pointer plus a count into the device-side view the containers expect, which is the operation that would otherwise be hand-written in every algorithm that needs one.
The build, the CI, and where the documentation lives
The repository is a conventional CMake C++ project. At the top level there is CMakeLists.txt, a cmake/ directory, src/, tests/, benchmarks/, examples/, docs/ and tools/, plus .clang-format and .clang-tidy for the formatting and lint configuration, a CONTRIBUTING.md and a LICENSE.
The presence of both .clang-format and .clang-tidy is a good sign for a library that has to compile under three different compilers and two different device toolchains, since the formatting and the lint rules are pinned in the repository rather than left to a contributor's editor.
The documentation is Doxygen based, at stotko.github.io/stdgpu, and the README links each container and each helper group to its generated class page, so the class reference is generated from the headers rather than written by hand.
The getting started instructions are in that documentation site rather than in the README, so the install path for the library is the docs and the CMake build with the backend you want enabled. The CONTRIBUTING.md covers the contribution process, and the examples directory has its own README alongside its CMakeLists.txt, so the examples are built as part of the project rather than as loose snippets.
On maintenance, the last push was on 2026-09-12, which is recent, but the last tagged release is 1.3.0 from 2020-06-02. That gap is worth reading carefully before you pin a version: the code is being worked on, and the released artifacts are six years old, so building from source against a recent commit is the likely path rather than a version pin.
Editorial conclusion
stdgpu fits a project doing real data management on the device, where the bottleneck is set membership or a hash lookup rather than arithmetic, and where you want container semantics rather than a raw memory pool. It is a poor fit for a numeric kernel that thrust or ArrayFire already covers, since stdgpu is deliberately orthogonal to those, and a poor fit if you need HIP, because that backend is experimental. Before adopting, read the getting started section in the documentation site and check whether your algorithm needs the high-level agnostic interface or the low-level native one, since the library is designed for you to use both.
Frequently asked questions
What is stdgpu?
stdgpu is an open-source C++17 library providing generic GPU data structures for fast and reliable data management. It offers familiar STL-like containers including atomic, atomic_ref, bitset, deque, queue, stack, unordered_map, unordered_set and vector, with CUDA, OpenMP and experimental HIP backends, and interoperability with thrust.
How does stdgpu differ from thrust, VexCL or ArrayFire?
The README says those libraries focus on the fast and efficient implementation of algorithms and only operate on contiguously stored data, while stdgpu follows an orthogonal approach focused on fast and reliable data management. The division of labour is that thrust covers algorithms over contiguous arrays and stdgpu covers the data structures when the data is not contiguous.
What is the difference between agnostic and native code in stdgpu?
Agnostic code uses the container through a generic interface, with functions like insert(begin, end), so shared C++ code can be written and thrust algorithms can be used. Native code uses low-level container functions like find(key) inside custom CUDA kernels with the CUDA backend enabled, for operations a generic interface cannot express.
Which GPU backends does stdgpu support?
CUDA, OpenMP and HIP, with HIP marked experimental in the feature list. The CI has separate tests.yml and lint.yml workflows labelled OpenMP, so the OpenMP path is tested and linted independently, and the examples directory has cuda, hip and openmp subdirectories.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/stotko-stdgpu)Star history chart for your README
[](https://hysenlabs.com/projects/stotko-stdgpu)Was this useful?