# External Memory

> NumKong for C++

Every kernel takes plain pointers, so any CPU-accessible memory works: mmap, pinned buffers, CUDA unified memory, custom arenas.
C++ views wrap any pointer without ownership.
Owning containers accept any C++ Allocator.

```cpp
template <typename T>
struct cuda_allocator {
    using value_type = T;
    T *allocate(std::size_t n) { T *p;
        cudaMallocManaged(&p, n * sizeof(T), cudaMemAttachGlobal); 
        return p; }
    void deallocate(T *p, std::size_t) noexcept { cudaFree(p); }
};

nk_dot_f32_best(cuda_managed_ptr, cuda_managed_ptr, 1024, &dot, capabilities, NULL); // C ABI, any pointer
auto view = nk::tensor_view<nk::f32_t>(mmap_ptr, rows, columns);                      // non-owning view
auto v = nk::vector<float, cuda_allocator<float>>::zeros(1024);                       // allocator-aware owning
```

`#include <numkong/memory.hpp>`

## aligned_allocator

Cache-aligned allocator with non-throwing allocation.

```cpp
template <typename value_type_,
          std::size_t alignment_ = nk_default_alignment_k>
struct aligned_allocator
```

Allocation returns `nullptr` on failure instead of throwing. It is stateless and always compares equal.

- `alignment` `std::size_t`

## allocator

Adapts a C allocation policy and caller-owned stream to the container allocator interface.

```cpp
template <typename value_type_>
struct allocator
```

- `policy` `nk_allocator_t`
- `stream` `nk_stream_t`

