The below test executable demonstrates the problem. With the ever-growing range-size (N), the VRAM is never released and keeps accumulating… Using nvc++ version 2025.11
Please, advise.
/*
* Minimal reproducer: scoped #pragma acc data copyin leaks VRAM
* when allocation sizes vary across calls.
*
* Build:
* nvc++ -acc -gpu=cc100 -O2 -o vram_leak vram_leak_test4_min.cpp -ldl
*
* Expected: delta stays ~0 MB (memory freed at end of scoped block).
* Actual: delta grows monotonically, never stabilizes.
*/
#include <cstdio>
#include <cstdlib>
#include <dlfcn.h>
#include <openacc.h>
static size_t
gpu_free_mb(void)
{
size_t free_bytes, total_bytes;
typedef int (*cuMemGetInfo_t)(size_t *, size_t *);
static cuMemGetInfo_t fn;
if (!fn) {
void *h = dlopen("libcuda.so.1", RTLD_NOW | RTLD_GLOBAL);
if (h)
fn = (cuMemGetInfo_t)dlsym(h, "cuMemGetInfo_v2");
}
if (fn && fn(&free_bytes, &total_bytes) == 0)
return (free_bytes / (1024 * 1024));
return (0);
}
static void
run(size_t N)
{
double *buf = new double[N];
for (size_t i = 0; i < N; ++i)
buf[i] = 1.0;
#pragma acc data copyin(buf[0:N])
{
#pragma acc parallel loop
for (size_t i = 0; i < N; ++i)
buf[i] *= 2.0;
}
/* buf[0:N] should be freed here -- but it is not. */
delete[] buf;
}
int
main(void)
{
/* Prime-number element counts so every allocation is unique. */
static const size_t primes[] = {
500009, 520013, 540007, 560017, 580027,
600011, 620003, 640007, 660013, 680003,
700001, 720007, 740011, 760007, 780029,
800011, 820007, 840023, 860009, 880001,
900001, 920011, 940003, 960017, 980027,
};
const int niters = sizeof(primes) / sizeof(primes[0]);
run(1000); /* warm up the OpenACC runtime */
size_t base = gpu_free_mb();
size_t cum = 0;
printf("baseline: %zu MB free\n\n", base);
for (int i = 0; i < niters; i++) {
size_t N = primes[i];
cum += N * sizeof(double);
run(N);
size_t now = gpu_free_mb();
printf("iter %2d N=%7zu (%2zu MB) free=%5zu MB"
" delta=%4zd MB cumalloc=%3zu MB\n",
i, N, N * 8 / (1024 * 1024), now,
(long)base - (long)now, cum / (1024 * 1024));
}
printf("\ntotal leaked: %zd MB (cumulative allocs: %zu MB)\n",
(long)base - (long)gpu_free_mb(), cum / (1024 * 1024));
return (0);
}