You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何释放函数封装返回的CUDA纹理对象占用的显存?

解决方案

问题的核心是:cudaDestroyTextureObject仅销毁纹理对象本身,但不会自动释放关联的cudaArray_t显存资源,必须显式调用cudaFreeArray才能释放这部分内存。要解决泄漏,需要修改函数设计,让调用者能获取并管理cudaArray_t的生命周期,具体步骤如下:

1. 定义资源结构体,统一管理关联资源

创建一个结构体来封装纹理对象和对应的cudaArray_t,确保两者能被一起销毁:

#include <cuda_runtime.h>
#include "matrix.h" // Matlab mxArray相关头文件

typedef struct {
    cudaTextureObject_t texObj;
    cudaArray_t cudaArr;
} TextureResource;

2. 修改创建函数,返回完整资源结构体

调整mxArrayToTexture函数,通过输出参数返回包含cudaArray_t的资源结构体,同时在出错时及时释放已分配的资源:

cudaError_t mxArrayToTexture(const mxArray* mxArr, TextureResource* outResource) {
    if (!mxArr || !outResource) return cudaErrorInvalidValue;

    // 初始化输出结构体
    memset(outResource, 0, sizeof(TextureResource));

    // 1. 从mxArray获取维度、数据类型等信息(原有逻辑保留)
    const int* dims = mxGetDimensions(mxArr);
    size_t width = dims[0];
    size_t height = dims[1];
    size_t depth = (mxGetNumberOfDimensions(mxArr) >=3 ) ? dims[2] : 1;
    size_t dataSize = mxGetNumberOfElements(mxArr) * mxGetElementSize(mxArr);

    // 2. 创建cudaArray_t(原有逻辑保留,增加错误处理)
    cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc(8, 8, 8, 8, cudaChannelFormatKindUnsigned); // 示例,根据mxArray类型调整
    cudaError_t err = cudaMallocArray(&outResource->cudaArr, &channelDesc, width, height, depth);
    if (err != cudaSuccess) return err;

    // 3. 拷贝数据到cudaArray(原有逻辑保留,增加错误回滚)
    err = cudaMemcpyToArray(outResource->cudaArr, 0, 0, mxGetData(mxArr), dataSize, cudaMemcpyHostToDevice);
    if (err != cudaSuccess) {
        cudaFreeArray(outResource->cudaArr);
        outResource->cudaArr = NULL;
        return err;
    }

    // 4. 创建纹理资源和对象(原有逻辑保留)
    cudaResourceDesc resDesc;
    memset(&resDesc, 0, sizeof(resDesc));
    resDesc.resType = cudaResourceTypeArray;
    resDesc.res.array.array = outResource->cudaArr;

    cudaTextureDesc texDesc;
    memset(&texDesc, 0, sizeof(texDesc));
    // 根据需求设置纹理属性:寻址模式、过滤模式、读写模式等
    texDesc.addressMode[0] = cudaAddressModeClamp;
    texDesc.filterMode = cudaFilterModeLinear;
    texDesc.readMode = cudaReadModeElementType;

    err = cudaCreateTextureObject(&outResource->texObj, &resDesc, &texDesc, NULL);
    if (err != cudaSuccess) {
        cudaFreeArray(outResource->cudaArr);
        outResource->cudaArr = NULL;
        return err;
    }

    return cudaSuccess;
}

3. 实现配套销毁函数,统一释放资源

编写一个销毁函数,确保同时销毁纹理对象和cudaArray_t,避免调用者遗漏:

void destroyTextureResource(TextureResource* resource) {
    if (!resource) return;

    // 先销毁纹理对象
    if (resource->texObj != 0) {
        cudaDestroyTextureObject(resource->texObj);
        resource->texObj = 0;
    }

    // 再释放cudaArray显存
    if (resource->cudaArr != NULL) {
        cudaFreeArray(resource->cudaArr);
        resource->cudaArr = NULL;
    }
}

4. 使用示例

// 创建纹理资源
TextureResource texRes;
cudaError_t err = mxArrayToTexture(yourMxArray, &texRes);
if (err != cudaSuccess) {
    // 错误处理
}

// 使用纹理对象texRes.texObj进行CUDA计算...

// 销毁资源(必须调用此函数,而非单独调用cudaDestroyTextureObject)
destroyTextureResource(&texRes);

关键说明

  • cudaArray_t是独立的显存分配资源,纹理对象对象只是对它的引用,销毁纹理对象不会自动释放cudaArray_t的内存。
  • 创建过程中任何步骤失败时,都要及时释放已分配的cudaArray_t,避免中途泄漏。
  • 必须通过统一的销毁函数管理资源,不要让调用者单独操作cudaTextureObject_t和cudaArray_t,降低出错概率。

内容的提问来源于stack exchange,提问作者PBragg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:45:00