1

我是 mshadow 的新手,我不明白为什么我会从以下代码片段中得到这些输出:

TensorContainer<cpu, 2> lhs(Shape2(2, 3));
lhs = 1.0;
printf("%u %u\n", lhs.size(0), lhs.size(1));
printf("%u %u\n", lhs[0].shape_[0], lhs[0].shape_[1]);
printf("%u %u\n", lhs[0].size(0), lhs[0].size(1));

输出是:

2 3
3 4
3 3

为什么第二个和第三个输出这些数字?因为lhs[0]是一维的,所以我认为它们应该是完全一样的,即3 0. 谁能告诉我我错在哪里?提前致谢!

4

1 回答 1

1

你是对的,张量 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)。

于 2017-08-02T21:55:45.977 回答