Доступ к срезам столбцов 2D valarrays

Рассмотрим следующий фрагмент кода,

#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;
}

Здесь я могу получить доступ к фрагментам строк, но не к фрагментам столбцов (как указано в комментариях). Есть ли обходной путь для доступа к срезам столбцов? Этот поток не дает ответа.


person Naveen    schedule 03.10.2016    source источник


Ответы (1)


Во-первых, у вас нет 2D valarray. У вас есть valarray из valarrays, разница, которую вы не должны игнорировать.

x = g[m][n];

только выглядит как доступ в стиле массива. Это действительно ближе к

temp = g[m];
x = temp[n];

Хранилище данных valarray представляет собой хороший непрерывный блок памяти, но если у вас есть структура M на N, у вас есть M+1 valarray, потенциально разбросанных по всей памяти. Это может превратиться в кошмар промахов кеша, убивающих производительность.

Вам придется решить, что более важно для быстрой работы, нарезка строк или нарезка столбцов, потому что только один из них будет работать с потоком памяти, а другой потребует копирования кэш-памяти против зерна.

В настоящее время

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

работает, потому что он нарезает непрерывный блок памяти, и

g[std::slice(0,1,3)][0]

терпит неудачу, потому что он должен пройти через M различных valarrays, чтобы собрать срез, а std::slice не может этого сделать. Вам придется вручную скопировать нужные элементы из каждого из valarray, составляющих столбец. Отстой, да?

Ну так что ты делаешь?

Вы притворяетесь! Мухахахахахахахаха!

Не делайте valarray из valarrays. Сделайте один большой valarray размером MxN. Так что попрощайтесь с

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

и привет

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

Теперь вы можете воспользоваться параметром шага std::slice, чтобы захватить каждый десятый элемент.

std::slice(column_to_slice,4,10);

И в качестве дополнительного бонуса у вас теперь есть один непрерывный блок памяти, поэтому, по крайней мере, некоторые из этих злоупотреблений кэш-памятью должны быть смягчены. Вы все равно смурфитесь, если шаг слишком велик.

Я искренне рекомендую обернуть это в объект, чтобы упростить доступ и управление. Что-то вроде этого, за исключением того, что вы используете valarray вместо исходного указатель.

person user4581301    schedule 03.10.2016
comment
Я пытался избежать превращения его в 1D valarray, но я думаю, что нет никакого способа обойти это. - person Naveen; 04.10.2016