昇腾社区首页
中文
注册
开发者
下载

aclDumpOpTensors

功能说明

模型执行过程中支持Dump算子输入/输出Tensor数据,方便算子输入/输出异常数据的问题定位和分析。

函数原型

aclnnStatus aclDumpOpTensors(const char *opType, const char *opName, aclTensor **tensors, size_t inputTensorNum, size_t outputTensorNum, aclrtStream stream)

参数说明

参数名

输入/输出

说明

opType

输入

字符串,表示算子类型,例如“Add”。

opName

输入

字符串,表示算子名称,例如“add_custom”。

tensors

输入

一维张量,表示待Dump的输入/输出Tensor对象指针。注意Tensor顺序,输入Tensor在前,输出Tensor在后。

inputTensorNum

输入

表示待Dump的输入Tensor个数。

outputTensorNum

输入

表示待Dump的输出Tensor个数。

stream

输入

指定执行任务的Stream。

返回值说明

返回0表示成功,返回其他值表示失败,返回码列表参见公共接口返回码

约束说明

本接口需要在开启算子Dump功能时有效,您可以通过“acl API参考(C) > 初始化和去初始化 > aclInit”接口开启Dump,也可以通过aclmdlInitDump、aclmdlSetDump、aclmdlFinalizeDump系列接口(参见“acl API参考 > Dump配置”)开启Dump。

调用示例

关键代码示例如下(仅供参考,不支持直接拷贝运行)。

  1. 通过aclInit接口使能算子Dump功能。关键代码如下:
    1
    2
    3
    4
    5
    // AscendCL Init
    aclInit("./acl.json");
    aclrtSetDevice(0);
    aclrtStream stream = nullptr;
    aclrtCreateStream(&stream)
    
    acl.json示例如下(具体参见aclInit接口文档中模型Dump配置、单算子Dump配置示例):
    1
    2
    3
    4
    5
    6
    7
    8
    {
        "dump": {
            "dump_path": "./",
    	"dump_list": [],
    	"dump_mode": "all",
    	"dump_data": "tensor"
        }
    }
    
  2. 接口调用的关键伪代码(以torch算子为例)如下:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    // 将at::Tensor转换成aclTensor对象
    aclTensor *ConvertTensor(const at::Tensor &at_tensor)
    {
        at::ScalarType scalar_data_type = at_tensor.scalar_type();
        aclDataType acl_data_type = at_npu::native::OpPreparation::convert_to_acl_data_type(scalar_data_type);
        c10::SmallVector<int64_t, MAX_DIM_NUM> storageDims;
    
        const auto dimNum = at_tensor.sizes().size();
        aclFormat format = ACL_FORMAT_ND;
        if (!at_npu::native::FormatHelper::IsOpInputBaseFormat(at_tensor)) {
            format = torch_npu::NPUBridge::GetNpuStorageImpl(at_tensor)->npu_desc_.npu_format_;
            // if acl_data_type is ACL_STRING, storageDims is empty.
            if (acl_data_type != ACL_STRING) {
                storageDims = torch_npu::NPUBridge::GetNpuStorageImpl(at_tensor)->npu_desc_.storage_sizes_;
            }
        } else {
            switch (dimNum) {
                case NCL_DIM_NUM:
                    format = ACL_FORMAT_NCL;
                    break;
                case NCHW_DIM_NUM:
                    format = ACL_FORMAT_NCHW;
                    break;
                case NCDHW_DIM_NUM:
                    format = ACL_FORMAT_NCDHW;
                    break;
                default:
                    format = ACL_FORMAT_ND;
            }
            // if acl_data_type is ACL_STRING, storageDims is empty.
            if (acl_data_type != ACL_STRING) {
                storageDims.push_back(at_tensor.storage().nbytes() / at_tensor.itemsize());
            }
        }
    
        if (at_npu::native::OpPreparation::is_scalar_wrapped_to_tensor(at_tensor)) {
            c10::Scalar expScalar = at_tensor.item();
            at::Tensor aclInput = at_npu::native::OpPreparation::copy_scalar_to_device(expScalar, scalar_data_type);
            return aclCreateTensor(aclInput.sizes().data(), aclInput.sizes().size(), acl_data_type,
                                   aclInput.strides().data(), aclInput.storage_offset(), format, storageDims.data(),
                                   storageDims.size(), const_cast<void *>(aclInput.storage().data()));
        }
    
        auto acl_tensor =
            aclCreateTensor(at_tensor.sizes().data(), at_tensor.sizes().size(), acl_data_type, at_tensor.strides().data(),
                            at_tensor.storage_offset(), format, storageDims.data(), storageDims.size(),
                            const_cast<void *>(at_tensor.storage().data()));
        return acl_tensor;
    }
    
    // 生成待Dump的输入/输出Tensor对象指针数组
    #define INIT_ACL_TENSOR_ARRAY(tensors, ...) aclTensor* tensors[] = {__VA_ARGS__}
    
    namespace ascendc_ops {
    at::Tensor ascendc_add(const at::Tensor& x, const at::Tensor& y)
    {
        auto aclStream = c10_npu::getCurrentNPUStream().stream(false);
        at::Tensor z = at::empty_like(x);
        uint32_t numBlocks = 8;
        uint32_t totalLength = 1;
        for (uint32_t size : x.sizes()) {
            totalLength *= size;
        }
        add_custom<<<numBlocks, nullptr, aclStream>>>((uint8_t*)(x.mutable_data_ptr()), (uint8_t*)(y.mutable_data_ptr()), (uint8_t*)(z.mutable_data_ptr()), totalLength);
        INIT_ACL_TENSOR_ARRAY(tensors, ConvertTensor(x), ConvertTensor(y), ConvertTensor(z));
        // Dump算子输入/输出Tensor数据
        aclDumpOpTensors("Add", "add_custom", tensors, 2, 1, aclStream);
        return z;
    }
    }