你是对的,张量 lhs[0] 是一维的,但首先要回答你的问题,让我展示一下幕后发生的事情。TensorContainer 不会覆盖 [] 运算符,而是使用来自父级(即 Tensor)的运算符,更准确地说,调用以下运算符:
MSHADOW_XINLINE Tensor<Device, kSubdim, DType> operator[](index_t idx) const {
return Tensor<Device, kSubdim, DType>(dptr_ + this->MemSize<1>() * idx,
shape_.SubShape(), stride_, stream_);
}
可以看出,它在堆栈上创建了一个新的张量。虽然在大多数情况下它将创建通用的 N 维张量,但对于一维情况,它将创建一个特殊的一维张量。
现在,当我们确定运算符 [] 究竟返回什么后,让我们看看该类的字段:
DType *dptr_;
Shape<1> shape_;
index_t stride_;
可以看出这里的 shape_ 只有一维!所以没有 shape_ 1,而是通过调用 shape_ 1它将返回 stride_ (或它的一部分)。这是对 Tensor 构造函数的修改,您可以尝试运行它并查看那里实际发生了什么:
MSHADOW_XINLINE Tensor(DType *dptr, Shape<1> shape,
index_t stride, Stream<Device> *stream)
: dptr_(dptr), shape_(shape), stride_(stride), stream_(stream) {
std::cout << "shape[0]: " << shape[0] << std::endl; // 3
std::cout << "shape[1]: " << shape[1] << std::endl; // 0, as expected
std::cout << "_shape[0]: " << shape_[0] << std::endl; // 3, as expected
std::cout << "_shape[1]: " << shape_[1] << std::endl; // garbage (4)
std::cout << "address of _shape[1]: " << &(shape_[1]) << std::endl;
std::cout << "address of stride: " << &(stride_) << std::endl;
}
和输出:
shape[0]: 3
shape[1]: 0
_shape[0]: 3
_shape[1]: 4
address of _shape[1]: 0x7fffa28ec44c
address of stride: 0x7fffa28ec44c
_shape 1和 stride 具有相同的地址 (0x7fffa28ec44c)。