如何访问ConstantNode的数值?假设已知:const ConstantNode *cnode;
ConstantNode类含有public类型的NDArray data,cnode->data就是runtime::NDArray类。
class ConstantNode : public ExprNode {public:/*! \brief The data of the tensor */runtime::NDArray data;
NDArray包含protected Container data
protected:/*! \brief Internal Data content */Container* data_{nullptr};
所以,通过ConstantNode类对象无法直接访问该data
但是,NDArray提供了operator->()操作符,可以访问该data
inline const DLTensor* NDArray::operator->() const {return &(data_->dl_tensor);}
Container包含DLTensor dl_tensor;
class NDArray::Container {public:// NOTE: the first part of this structure is the same as// DLManagedTensor, note that, however, the deleter// is only called when the reference counter goes to 0/*!* \brief The corresponding dl_tensor field.* \note it is important that the first field is DLTensor* So that this data structure is DLTensor compatible.* The head ptr of this struct can be viewed as DLTensor*.*/DLTensor dl_tensor;
DLTensor结构体定义如下:
typedef struct {/*!* \brief The opaque data pointer points to the allocated data. This will be* CUDA device pointer or cl_mem handle in OpenCL. This pointer is always* aligns to 256 bytes as in CUDA.** For given DLTensor, the size of memory required to store the contents of* data is calculated as follows:** \code{.c}* static inline size_t GetDataSize(const DLTensor* t) {* size_t size = 1;* for (tvm_index_t i = 0; i < t->ndim; ++i) {* size *= t->shape[i];* }* size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;* return size;* }* \endcode*/void* data;/*! \brief The device context of the tensor */DLContext ctx;/*! \brief Number of dimensions */int ndim;/*! \brief The data type of the pointer*/DLDataType dtype;/*! \brief The shape of the tensor */int64_t* shape;/*!* \brief strides of the tensor,* can be NULL, indicating tensor is compact.*/int64_t* strides;/*! \brief The offset in bytes to the beginning pointer to data */uint64_t byte_offset;} DLTensor;
所以,假设给定一个ConstantNode类指针对象:
ConstantNode* cnode;
NDArray nd= **cnode->data;
那么nd.operator->()表示一个DLTensor指针类
所以,nd->data就能直接访问**DLTensor的data
注意,通过如下方式可以获取DLTensor的总大小(字节数)和数据个数
static inline size_t GetDataSize(const DLTensor* t) {size_t size = 1;for (tvm_index_t i = 0; i < t->ndim; ++i) {size *= t->shape[i];}size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;return size;}static inline size_t GetDataNumber(const DLTensor* t) {size_t size = 1;for (tvm_index_t i = 0; i < t->ndim; ++i) {size *= t->shape[i];}size *= (t->dtype.bits * t->dtype.lanes + 7) / 8;return size;}
if (const ConstantNode* rhs = other.as<ConstantNode>()) {return NDArrayEqual(lhs->data, rhs->data);//此处,rhs->data就是指向NDArray *}
示例:
Expr ExpandConstantNode(const ConstantNode* const_node, std::string layout_name) {runtime::NDArray src_ret = const_node->data;TensorType tensor_type = const_node->tensor_type();int64_t OC, IC;std::vector<int64_t> src_shape;Array<IndexExpr> tensor_shape = tensor_shape;for (size_t i = 0; i < tensor_shape.size(); ++i) {int64_t sz_i = *as_const_int(tensor_shape[i]);src_shape.push_back(sz_i);}OC = src_shape[0];IC = src_shape[1];std::vector<int64_t> dst_shape;dst_shape.assign(src_shape.begin(), src_shape.end());dst_shape[0] = OC * 2; // duble the OCdst_shape[1] = IC;auto dst_ndarray = runtime::NDArray::Empty(dst_shape, tensor_type->dtype.operator DLDataType(), {kDLCPU, 0});DLTensor* dst = const_cast<DLTensor*>(dst_ndarray.operator->());SimpleDataType data_type = GetSimpleDataType(tensor_type->dtype);if (data_type == DATA_FP16) {// FP16ExpandWeight<uint16_t>(src_ret.operator->(), dst, src_shape, dst_shape, layout_name);} else if (data_type == DATA_FLOAT) {// FP32 for testingExpandWeight<float>(src_ret.operator->(), dst, src_shape, dst_shape, layout_name);} else {// INT8ExpandWeight<char>(src_ret.operator->(), dst, src_shape, dst_shape, layout_name);}auto new_constant = ConstantNode::make(dst_ndarray);return new_constant;}};
