考虑以下代码片段,

#include <iostream>
#include <valarray>

using namespace std;

std::ostream & operator<<(std::ostream & out, const std::valarray<int> inputVector);
typedef std::valarray<std::valarray<int> > val2d;

int main()
{
    val2d g(std::valarray<int>(10),4);

    for (uint32_t n=0; n<4; ++n){
        for (uint32_t m=0; m<10; ++m){
            g[n][m] = n*10 + m;
        }
    }
   std::valarray<int> g_slice_rs = g[1][std::slice(0,10,1)];  // row slice
   //std::valarray<int> g_slice_cs = g[std::slice(0,1,3)][0];   // column slice (comment out)

   cout<<"row slice :: "<<g_slice_rs<<endl;
   //cout<<"column slice :: "<<g_slice_cs<<endl; // (comment out)
   return 0;
}

std::ostream & operator<<(std::ostream & out, const std::valarray<int> inputVector)
{
  uint32_t vecLength = inputVector.size();
  out<<"[";
  for (uint32_t i=0; i<vecLength; ++i)
  {
    out <<inputVector[i]<<", ";
  }
  out<<"]"<<endl;
  return out;
}

在这里,我可以访问行 slice ,但不能访问列 slice (如注释中所示)。有没有解决方法来访问列 slice ? This线程不提供答案。

最佳答案

首先,您没有2D valarray。您的valarrayvalarray,这是您不应该忽略的差异。

x = g[m][n];

只看起来像一个数组样式的访问。真的更接近
temp = g[m];
x = temp[n];
valarray的数据存储区是一个不错的连续内存块,但是如果您使用M by N结构,则可能有M + 1 valarray散布在整个内存中。这可能会成为导致性能下降的高速缓存未命中的噩梦。

您将必须确定行速 slice 或列 slice 中哪一个更为重要,因为要快速执行,是行 slice 还是列 slice ,因为只有一个要处理内存流,而另一个需要对粒度进行高速缓存复制。

目前
g[1][std::slice(0,10,1)];

之所以有效,是因为它正在分割一个连续的内存块,并且
g[std::slice(0,1,3)][0]

失败,因为它必须跨越M个不同的valarray来收集 slice ,而std::slice无法做到这一点。您将必须从组成该列的每个valarray中手动复制所需的元素。糟透了吧?

所以你会怎么做?

你假的! Muhuhahahahahahahahaha!

不要将valarray设为valarray。制作一个大小为MxN的大valarray。所以说再见
std::valarray<std::valarray<int> > g(std::valarray<int>(10),4);

和你好
std::valarray<int>(10*4);

现在,您可以利用std::slice的stride参数获取每十分之一的元素
std::slice(column_to_slice,4,10);

作为额外的好处,您现在拥有一个连续的内存块,因此至少应减轻某些缓存粉碎滥用。如果跨度太大,您仍然会感到困惑。

我全心全意地建议将其包装在一个对象中,以简化访问和管理。 Something like this,除了您使用valarray而不是原始指针。

关于c++ - 访问2D valarray的列切片,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39841525/

10-09 15:33