Skip to content

Instantly share code, notes, and snippets.

@chengscott
Created January 30, 2025 10:21
Show Gist options
  • Save chengscott/520657eb9dc0d2fae9ba635bacb28fd6 to your computer and use it in GitHub Desktop.
Save chengscott/520657eb9dc0d2fae9ba635bacb28fd6 to your computer and use it in GitHub Desktop.
host_vector (a std::vector with a custom allocator based on cudaMallocHost)
#include "host_vector.hpp"
#define DEVICE_CHECK(call) \
if ((call) != cudaSuccess) { \
throw std::runtime_error(#call " API call failed: " + GetLastErrorString() + " at " + \
__FILE__ + ", line" + std::to_string(__LINE__)); \
}
static std::string GetLastErrorString() { return cudaGetErrorString(cudaGetLastError()); }
namespace details {
void device_malloc_host(void **h_ptr, std::size_t size) { DEVICE_CHECK(cudaMallocHost(h_ptr, size)); }
void *device_malloc_host(size_t size) {
void *h_ptr;
device_malloc_host(&h_ptr, size);
return h_ptr;
}
void free_device_host_memory_safe(void *h_ptr) {
if (h_ptr != nullptr) {
DEVICE_CHECK(cudaFreeHost(h_ptr));
}
}
} // namespace details
#include <vector>
namespace details {
void *device_malloc_host(std::size_t);
void free_device_host_memory_safe(void *);
template <typename T> struct HostAllocator : public std::allocator<T> {
template <class U> struct rebind { using other = HostAllocator<U>; };
T *allocate(std::size_t n) { return static_cast<T *>(device_malloc_host(n * sizeof(T))); }
void deallocate(T *ptr, std::size_t) noexcept { free_device_host_memory_safe(ptr); }
};
} // namespace details
template <typename T> using host_vector = std::vector<T, details::HostAllocator<T>>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment