如何访问ConstantNode的数值?假设已知:const ConstantNode *cnode;

    ConstantNode类含有public类型的NDArray data,cnode->data就是runtime::NDArray类。

    1. class ConstantNode : public ExprNode {
    2. public:
    3. /*! \brief The data of the tensor */
    4. runtime::NDArray data;

    NDArray包含protected Container data

    1. protected:
    2. /*! \brief Internal Data content */
    3. Container* data_{nullptr};

    所以,通过ConstantNode类对象无法直接访问该data
    但是,NDArray提供了operator->()操作符,可以访问该data

    1. inline const DLTensor* NDArray::operator->() const {
    2. return &(data_->dl_tensor);
    3. }

    Container包含DLTensor dl_tensor;

    1. class NDArray::Container {
    2. public:
    3. // NOTE: the first part of this structure is the same as
    4. // DLManagedTensor, note that, however, the deleter
    5. // is only called when the reference counter goes to 0
    6. /*!
    7. * \brief The corresponding dl_tensor field.
    8. * \note it is important that the first field is DLTensor
    9. * So that this data structure is DLTensor compatible.
    10. * The head ptr of this struct can be viewed as DLTensor*.
    11. */
    12. DLTensor dl_tensor;

    DLTensor结构体定义如下:

    1. typedef struct {
    2. /*!
    3. * \brief The opaque data pointer points to the allocated data. This will be
    4. * CUDA device pointer or cl_mem handle in OpenCL. This pointer is always
    5. * aligns to 256 bytes as in CUDA.
    6. *
    7. * For given DLTensor, the size of memory required to store the contents of
    8. * data is calculated as follows:
    9. *
    10. * \code{.c}
    11. * static inline size_t GetDataSize(const DLTensor* t) {
    12. * size_t size = 1;
    13. * for (tvm_index_t i = 0; i < t->ndim; ++i) {
    14. * size *= t->shape[i];
    15. * }
    16. * size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;
    17. * return size;
    18. * }
    19. * \endcode
    20. */
    21. void* data;
    22. /*! \brief The device context of the tensor */
    23. DLContext ctx;
    24. /*! \brief Number of dimensions */
    25. int ndim;
    26. /*! \brief The data type of the pointer*/
    27. DLDataType dtype;
    28. /*! \brief The shape of the tensor */
    29. int64_t* shape;
    30. /*!
    31. * \brief strides of the tensor,
    32. * can be NULL, indicating tensor is compact.
    33. */
    34. int64_t* strides;
    35. /*! \brief The offset in bytes to the beginning pointer to data */
    36. uint64_t byte_offset;
    37. } DLTensor;

    所以,假设给定一个ConstantNode类指针对象:
    ConstantNode* cnode;
    NDArray nd= **cnode->data;
    那么nd.operator->()表示一个DLTensor指针类
    所以,nd->data就能直接访问**DLTensor的data

    注意,通过如下方式可以获取DLTensor的总大小(字节数)和数据个数

    1. static inline size_t GetDataSize(const DLTensor* t) {
    2. size_t size = 1;
    3. for (tvm_index_t i = 0; i < t->ndim; ++i) {
    4. size *= t->shape[i];
    5. }
    6. size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;
    7. return size;
    8. }
    9. static inline size_t GetDataNumber(const DLTensor* t) {
    10. size_t size = 1;
    11. for (tvm_index_t i = 0; i < t->ndim; ++i) {
    12. size *= t->shape[i];
    13. }
    14. size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;
    15. return size;
    16. }
    1. if (const ConstantNode* rhs = other.as<ConstantNode>()) {
    2. return NDArrayEqual(lhs->data, rhs->data);//此处,rhs->data就是指向NDArray *
    3. }

    示例:

    1. Expr ExpandConstantNode(const ConstantNode* const_node, std::string layout_name) {
    2. runtime::NDArray src_ret = const_node->data;
    3. TensorType tensor_type = const_node->tensor_type();
    4. int64_t OC, IC;
    5. std::vector<int64_t> src_shape;
    6. Array<IndexExpr> tensor_shape = tensor_shape;
    7. for (size_t i = 0; i < tensor_shape.size(); ++i) {
    8. int64_t sz_i = *as_const_int(tensor_shape[i]);
    9. src_shape.push_back(sz_i);
    10. }
    11. OC = src_shape[0];
    12. IC = src_shape[1];
    13. std::vector<int64_t> dst_shape;
    14. dst_shape.assign(src_shape.begin(), src_shape.end());
    15. dst_shape[0] = OC * 2; // duble the OC
    16. dst_shape[1] = IC;
    17. auto dst_ndarray = runtime::NDArray::Empty(
    18. dst_shape, tensor_type->dtype.operator DLDataType(), {kDLCPU, 0});
    19. DLTensor* dst = const_cast<DLTensor*>(dst_ndarray.operator->());
    20. SimpleDataType data_type = GetSimpleDataType(tensor_type->dtype);
    21. if (data_type == DATA_FP16) {
    22. // FP16
    23. ExpandWeight<uint16_t>(src_ret.operator->(), dst, src_shape, dst_shape, layout_name);
    24. } else if (data_type == DATA_FLOAT) {
    25. // FP32 for testing
    26. ExpandWeight<float>(src_ret.operator->(), dst, src_shape, dst_shape, layout_name);
    27. } else {
    28. // INT8
    29. ExpandWeight<char>(src_ret.operator->(), dst, src_shape, dst_shape, layout_name);
    30. }
    31. auto new_constant = ConstantNode::make(dst_ndarray);
    32. return new_constant;
    33. }
    34. };