Repository: ggerganov/llama.cpp
File: ggml/src/ggml-cuda/ggml-cuda.cu (CUDA)

Code before:
        // Hugetlbfs pages are not swappable.
        *freeSwapKb = 0;
    }

    GGML_LOG_DEBUG("%s: final availableMemoryKb: %ld\n", __func__, *availableMemoryKb);
    return true;
}
#endif // defined(__linux__)

static void ggml_backend_cuda_device_get_memory(ggml_backend_dev_t dev, size_t * free, size_t * total) {
    ggml_backend_cuda_device_context * ctx = (ggml_backend_cuda_device_context *)dev->context;
    ggml_cuda_set_device(ctx->device);
    CUDA_CHECK(cudaMemGetInfo(free, total));

#if defined(__linux__)
    // Check if this is a UMA (Unified Memory Architecture) system
    cudaDeviceProp prop;
    CUDA_CHECK(cudaGetDeviceProperties(&prop, ctx->device));

    GGML_LOG_DEBUG("%s: prop.name: %s\n", __func__, prop.name);
    GGML_LOG_DEBUG("%s: prop.unifiedAddressing: %d\n", __func__, prop.unifiedAddressing);

    // Check if UMA is explicitly enabled via environment variable
    const char * uma_env = getenv("GGML_CUDA_ENABLE_UNIFIED_MEMORY");

    bool is_uma = prop.unifiedAddressing > 0 || (uma_env != nullptr && uma_env[0] == '1');

    GGML_LOG_DEBUG("%s: is_uma: %d\n", __func__, is_uma);

    if (is_uma) {
        // For UMA systems (like DGX Spark), use system memory info
        long availableMemoryKb = 0;
        long freeSwapKb = 0;

        if (ggml_backend_cuda_get_available_uma_memory(&availableMemoryKb, &freeSwapKb) && availableMemoryKb > 0) {
            *free = (size_t)availableMemoryKb * 1024;
        } else {
            GGML_LOG_ERROR("%s: /proc/meminfo reading failed, using cudaMemGetInfo\n", __func__);
        }
    }

    GGML_LOG_DEBUG("%s: free:  %8.2f MB\n", __func__, *free / (1024.0 * 1024.0));
    GGML_LOG_DEBUG("%s: total: %8.2f MB\n", __func__, *total / (1024.0 * 1024.0));
#endif // defined(__linux__)

}

static enum ggml_backend_dev_type ggml_backend_cuda_device_get_type(ggml_backend_dev_t dev) {
    GGML_UNUSED(dev);
    return GGML_BACKEND_DEVICE_TYPE_GPU;
}

Review comment (suggestion):
Use `GGML_CUDA_ENABLE_UNIFIED_MEMORY` consistently: in `ggml_cuda_device_malloc` it only matters if the variable exists, the value itself is ignored.

Code after:
}
#endif // defined(__linux__)

static void ggml_backend_cuda_device_get_memory(ggml_backend_dev_t dev, size_t * free, size_t * total) {
    ggml_backend_cuda_device_context * ctx = (ggml_backend_cuda_device_context *)dev->context;
    ggml_cuda_set_device(ctx->device);
    CUDA_CHECK(cudaMemGetInfo(free, total));

// ref: https://github.com/ggml-org/llama.cpp/pull/17368
#if defined(__linux__)
    // Check if this is a UMA (Unified Memory Architecture) system
    cudaDeviceProp prop;
    CUDA_CHECK(cudaGetDeviceProperties(&prop, ctx->device));

    // Check if UMA is explicitly enabled via environment variable
    bool uma_env = getenv("GGML_CUDA_ENABLE_UNIFIED_MEMORY") != nullptr;
    bool is_uma = prop.unifiedAddressing > 0 || uma_env;

    if (is_uma) {
        // For UMA systems (like DGX Spark), use system memory info
        long available_memory_kb = 0;
        long free_swap_kb = 0;

        if (ggml_backend_cuda_get_available_uma_memory(&available_memory_kb, &free_swap_kb) && available_memory_kb > 0) {
            *free = (size_t)available_memory_kb * 1024;
        } else {
            GGML_LOG_ERROR("%s: /proc/meminfo reading failed, using cudaMemGetInfo\n", __func__);
        }
    }
#endif // defined(__linux__)

}

static enum ggml_backend_dev_type ggml_backend_cuda_device_get_type(ggml_backend_dev_t dev) {
    GGML_UNUSED(dev);
    return GGML_BACKEND_DEVICE_TYPE_GPU;
}

static void ggml_backend_cuda_device_get_props(ggml_backend_dev_t dev, ggml_backend_dev_props * props) {
    ggml_backend_cuda_device_context * ctx = (ggml_backend_cuda_device_context *)dev->context;

    props->name        = ggml_backend_cuda_device_get_name(dev);
    props->description = ggml_backend_cuda_device_get_description(dev);
    props->type        = ggml_backend_cuda_device_get_type(dev);
    props->device_id   = ctx->pci_bus_id.empty() ? nullptr : ctx->pci_bus_id.c_str();
    ggml_backend_cuda_device_get_memory(dev, &props->memory_free, &props->memory_total);

    bool host_buffer = getenv("GGML_CUDA_NO_PINNED") == nullptr;
#ifdef GGML_CUDA_NO_PEER_COPY
    bool events = false;
#else