将xt::view返回值赋值给xt::xarray是否会触发数据复制?
问题描述
我通过适配方式从OpenCV的Mat创建xt::xarray:
std::array<size_t, 3> shape = {static_cast<size_t>(img.rows), static_cast<size_t>(img.cols), 2}; xt::xarray<float> arr = xt::adapt(img.ptr<float>(), shape);
随后我写了一个生成线性间隔索引的辅助函数,调用方式如下:
xt::xarray<float> sparsified = sparsify(arr);
sparsify函数定义如下:
xt::xarray<float> sparsify(const xt::xarray<float> &arr) const { auto yIndices = xt::linspace<int>(0, arr.shape(0) - 1, _config._sparseGridY, false); auto xIndices = xt::linspace<int>(0, arr.shape(1) - 1, _config._sparseGridX, false); return xt::view(arr, xt::keep(yIndices), xt::keep(xIndices), xt::all()); }
请问将xt::view()的返回值赋值给xt::xarray时是否会复制数组数据?我希望尽可能减少数据复制操作。
解答
直接赋值会触发数据复制:
xt::view返回的是一个视图对象(类似xt::xview),它本身不持有数据,只是对原数组的引用。但当你把这个视图赋值给xt::xarray<float>类型的变量时,xarray会创建新的内存空间,把视图指向的数据拷贝进去——这一步会产生完整的数据复制。避免复制的两种方案:
改用视图类型存储结果:把
sparsified的类型改成auto或者明确的视图类型,这样就直接持有视图,完全不复制数据:auto sparsified = sparsify(arr); // 或者明确指定类型(推荐auto简化代码) xt::xview<const xt::xarray<float>, xt::keep_slice, xt::keep_slice, xt::all_slice> sparsified = sparsify(arr);注意:这种方式下,原数组
arr的生命周期必须长于视图sparsified,否则会出现悬垂引用。修改函数返回类型为视图:把
sparsify的返回类型从xt::xarray<float>改成视图类型,这样函数返回时也不会触发复制:auto sparsify(const xt::xarray<float> &arr) const { auto yIndices = xt::linspace<int>(0, arr.shape(0) - 1, _config._sparseGridY, false); auto xIndices = xt::linspace<int>(0, arr.shape(1) - 1, _config._sparseGridX, false); return xt::view(arr, xt::keep(yIndices), xt::keep(xIndices), xt::all()); }调用时用
auto接收返回值,就能直接获得视图,无数据复制。
额外提示:你最初用
xt::adapt创建arr时,默认会复制Mat的数据。如果想让xarray直接引用Mat的内存(避免第一次复制),需要加上xt::no_ownership标记:xt::xarray<float> arr = xt::adapt(img.ptr<float>(), shape, xt::no_ownership());同样要注意,原Mat的生命周期必须长于
arr,否则会出现内存访问错误。
内容的提问来源于stack exchange,提问作者Michal Majeran
相关产品推荐
相关产品推荐

