【问题标题】:Can I remove a single dimension of a boost::multi_array without copying its content?我可以在不复制其内容的情况下删除 boost::multi_array 的单个维度吗?
【发布时间】:2013-07-14 10:52:15
【问题描述】:

以下是我将 boost::multi_array 从形状 [3 4 2] 重塑为 [12 2] 的代码。由于维度在 boost::multi_array 中是固定的,我首先将三维数组重塑为形状 [12 2 1],然后将前两个维度复制到一个新数组中。

有没有更简单的方法不进行任何复制(我更希望本着numpy.reshape 的精神只查看原始数据)。

使用g++ -g test.cc && ./a.out运行

#include "boost/multi_array.hpp"                                                                                                                                                                                                                                                                                           
#include <cassert>                                                                                                                                                                                                                                                                                                         
#include <iostream>                                                                                                                                                                                                                                                                                                        


int                                                                                                                                                                                                                                                                                                                        
main () {                                                                                                                                                                                                                                                                                                                  
  // Create a 3D array that is 3 x 4 x 2                                                                                                                                                                                                                                                                                   
  typedef boost::multi_array<double, 3> array_type;                                                                                                                                                                                                                                                                        
  typedef array_type::index index;                                                                                                                                                                                                                                                                                         

  array_type A(boost::extents[3][4][2]);                                                                                                                                                                                                                                                                                   

  // indexer can be const a boost::array                                                                                                                                                                                                                                                                                   
  boost::array<array_type::index,3> idx = {{0,0,0}};                                                                                                                                                                                                                                                                       

  // Assign values to the elements                                                                                                                                                                                                                                                                                         
  int values = 0;                                                                                                                                                                                                                                                                                                          
  for(index i = 0; i != 3; ++i)                                                                                                                                                                                                                                                                                            
    for(index j = 0; j != 4; ++j)                                                                                                                                                                                                                                                                                          
      for(index k = 0; k != 2; ++k)                                                                                                                                                                                                                                                                                        
        A[i][j][k] = values++;                                                                                                                                                                                                                                                                                             
  std::cout << "array elements: " << A.num_elements() << std::endl;                                                                                                                                                                                                                                                        
  std::cout << "array ndim: " << A.num_dimensions() << std::endl;                                                                                                                                                                                                                                                          
  std::cout << "array size: " << A.size() << std::endl; // equivalent to a.shape()[0];                                                                                                                                                                                                                                     
  std::cout << "array shape: " << A.shape()[0] <<" " << A.shape()[1] <<" " << A.shape()[2] << std::endl;                                                                                                                                                                                                                   

  int verify = 0;                                                                                                                                                                                                                                                                                                          
  for(index i = 0; i != 3; ++i)                                                                                                                                                                                                                                                                                            
    for(index j = 0; j != 4; ++j)                                                                                                                                                                                                                                                                                          
      for(index k = 0; k != 2; ++k) {                                                                                                                                                                                                                                                                                      
        std::cout << "A[" <<i <<"]["<<j<<"]["<<k<<"] = " << A[i][j][k] << std::endl;                                                                                                                                                                                                                                       
        assert(A[i][j][k] == verify++);                                                                                                                                                                                                                                                                                    
      }                                                                                                                                                                                                                                                                                                                    

  boost::array<array_type::index,3> dims2 = {{12, 2, 1}};                                                                                                                                                                                                                                                                  
  A.reshape(dims2);                                                                                                                                                                                                                                                                                                        

  std::cout << "array shape: " << A.shape()[0] <<" " << A.shape()[1] <<" " << A.shape()[2] << std::endl;                                                                                                                                                                                                                   
  for(index i = 0; i != 12; ++i)                                                                                                                                                                                                                                                                                           
    for(index j = 0; j != 2; ++j)                                                                                                                                                                                                                                                                                          
      for(index k = 0; k != 1; ++k) {                                                                                                                                                                                                                                                                                      
        std::cout << "A[" <<i <<"]["<<j<<"]["<<k<<"] = " << A[i][j][k] << std::endl;                                                                                                                                                                                                                                       
      }                                                                                                                                                                                                                                                                                                                    

  typedef boost::multi_array<double, 2> Array2d;                                                                                                                                                                                                                                                                           
  Array2d B(boost::extents[12][2]);                                                                                                                                                                                                                                                                                        
  for(index i = 0; i != 12; ++i)                                                                                                                                                                                                                                                                                           
    for(index j = 0; j != 2; ++j){                                                                                                                                                                                                                                                                                         
      B[i][j] = A[i][j][0];                                                                                                                                                                                                                                                                                                
      std::cout << "B[" <<i <<"]["<<j<<"] = " << B[i][j] << std::endl;                                                                                                                                                                                                                                                     
    }                                                                                                                                                                                                                                                                                                                      
  return 0;                                                                                                                                                                                                                                                                                                                
}   

【问题讨论】:

    标签: c++ boost multidimensional-array


    【解决方案1】:

    事实证明,这可以通过使用 View(c.f. Creating Views)来实现。

    在我的例子中:

    ... reshape ...
    
    typedef boost::multi_array_types::index_range range;                                                                       
    array_type::index_gen indices;  
    array_type::array_view<2>::type myview =       
        A[ indices[range(0,12)][range(0,2)][0] ];                                   
    for(index i = 0; i != 12; ++i)      
      for(index j = 0; j != 2; ++j){  
        std::cout << "myview[" <<i <<"]["<<j<<"] = " << myview[i][j] << std::endl;  
    

    【讨论】:

      【解决方案2】:

      我认为在一般情况下您无法做到这一点。您可以做的是生成一个具有较低维度的 subview。我阅读了您的代码,您希望 2D 数组的元素数量与原始 3D 数组一样多。

      你可以做的是用const_multi_array_ref重用3D数组的现有数据:

      boost::multi_array< int, 3 > a( boost::extents[ 2 ][ 3 ][ 4 ] );
      boost::const_multi_array_ref< int, 2 > b( a.data(), boost::extents[ 2 ][ 12 ] );
      

      根据存储顺序,这可能会满足您的要求。

      我建议围绕 multi_array 编写一个小包装器,它使用所需的索引计算访问 multi_array

      【讨论】:

      • 感谢您的回答。这绝对比我的解决方案好。这条修改后的线符合我的要求:boost::const_multi_array_ref&lt; double, 2 &gt; B( A.data(), boost::extents[ 12 ][ 2 ] );
      • 如果我正确理解multi_array::reshape 的作用,效果与我的方法相似(我仍然会考虑编写一个小的包装器以提高可读性和灵活性)。如果你觉得我的回答可以接受,请接受。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 2015-12-01
      • 2020-04-30
      • 2012-06-10
      • 1970-01-01
      相关资源
      最近更新 更多