В каком контейнере STL есть возможности для нарезки на два или более контейнеров? - PullRequest
0 голосов
/ 20 мая 2011

Скажем, у меня есть вектор / список независимо от целых чисел, заполненных 2300 значениями
Я хочу иметь возможность легко разделить это на 4 вектора / списка (не обязательно одинакового размера).
например

vec1 ( elements 0 - 500 )
vec2 ( elements 501 - 999)
vec3 ( elements 1001 - 1499)


и т. Д.

Ответы [ 6 ]

4 голосов
/ 21 мая 2011

Обычный способ сделать это - использовать один контейнер и просто определить для него отдельные диапазоны итераторов.

std::vector<int> vec(2300);

it0 = vec.begin();
it1 = vec.begin() + 500;
it2 = vec.begin() + 1000;
it3 = vec.begin() + 1500;
it4 = vec.begin() + 2000;
it5 = vec.end();

Теперь первый диапазон просто определяется итераторами it0 и it1. Второе it1 и it2 и т. Д.

Итак, если вы хотите применить функцию к каждому элементу в третьем диапазоне, вы просто сделаете это:

std::for_each(it2, it3, somefunc);

На самом деле копирование элементов в отдельные контейнеры может быть ненужным и может привести к снижению производительности.

4 голосов
/ 20 мая 2011

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

EDIT

Согласно комментариям (спасибо за понимание), возможно, использование std::vector<int> и итераторов - хорошая идея. Однако с простыми итераторами вы теряете длину вектора, поэтому я предлагаю использовать, например, boost::range_iterator:

std::vector<int> vec(2300);

it0 = vec.begin();
it1 = vec.begin() + 500;
it2 = vec.begin() + 1000;
it3 = vec.begin() + 1500;
it4 = vec.begin() + 2000;
it5 = vec.end;

typedef boost::iterator_range< std::vector<int>::iterator > my_slice_t;

my_slice_t slice1 = boost::make_iterator_range(it0, it1);
...

Затем вы можете использовать slice1 как обычный, лежащий в основе std::vector<int> согласно итерации:

std::for_each(slice1.begin(), slice1.end(), /* stuff */);
2 голосов
/ 20 мая 2011

См. Четвертый std::vector<> документально подтвержденный конструктор здесь .

// given std::vector<T> vec with 2300 elements
std::vector<T> vec1(vec.begin(), vec.begin() + 500);
std::vector<T> vec2(vec.begin() + 500, vec.begin() + 1000);
std::vector<T> vec3(vec.begin() + 1000, vec.begin() + 1500);
std::vector<T> vec4(vec.begin() + 1500, vec.begin() + 2000);
std::vector<T> vec5(vec.begin() + 2000, vec.end());
1 голос
/ 21 мая 2011

На самом деле это выполнимо с векторным контейнером

#include <vector>
#include <iostream>

using namespace std ;

int main()
{
  vector<int> ints ;
  vector<int> ints_sliced;

  int i ;

  // populate
  for( i = 0 ; i < 100 ; i++ ) 
    ints.push_back(i) ;

  // slice from 10-19
  ints_sliced.insert(ints_sliced.begin(), ints.begin()+10, ints.begin()+20) ;

  // inspect
  vector<int>::iterator it ;
  for( it = ints_sliced.begin() ; it != ints_sliced.end() ; it++ )
    cout << *it << endl ;



}
0 голосов
/ 21 мая 2011

О, если вы используете g ++ и GNU stdlibc ++, вы можете использовать примерно

g++ -march=native -O3 -ftree-vectorize ...

Если вы также добавите поддержку GNU OpenMP (libgomp), вы можете извлечь выгоду ( оценивать, профиль !) Из автоматического распараллеливания стандартных алгоритмов,

g++ -D_GLIBCXX_PARALLEL -fopenmp -march=native -O3 .... -lgomp

YMMV - Я хотел просто выбросить это, потому что, например, параллель for_each, кажется, близка к тому, что вы хотите (но автоматическая и самоадаптирующаяся к размеру контейнера, типу итератора и количеству процессоров)

0 голосов
/ 21 мая 2011

В дополнение к правильному замечанию @ jalf, что фактическое копирование подвекторов в свежие векторы может быть пустой тратой времени и пространства, позвольте мне указать на valarray .

Intro: valarray

Valarray может быть более сложным, но особенно в условиях параллельной обработки, может привести к улучшению способов подвекторной работы для различных потоков.Что нужно искать:

  1. алгоритмическая предварительная наука (если местоположения в определенном шаблоне имеют определенное свойство (например, известно, что оно равно нулю), вы можете передать его оптимизированному рабочему для этих значений)
  2. выравнивание субвекторов (с помощью aligment можно создавать или нарушать доступность SIMD, оптимизированных версий SSE4; для получения дополнительной информации обратитесь к gcc -ftree-vectorizer)

Теперь в Valarrays достаточноряд «непонятных» операций и хитростей к ним (gslices; в основном, измеренные размеры массива для адресации к исходному массиву), которые я не буду здесь вдаваться, но достаточно сказать, что если вы хотите выполнить сжатие чисел через подмножества смежныхмассивы (в основном) с плавающей точкой [1], это будет полезно прочитать о них.

Обязательный (braindead) тизер

// mask_array example
#include <iostream>
#include <valarray>
using namespace std;

int main ()
{
  valarray<int> myarray (10);
  for (int i=0; i<10; ++i) myarray[i]=i;   //  0  1  2  3  4  5  6  7  8  9

  valarray<bool> mymask (10);
  for (int i=0; i<10; ++i)
    mymask[i]= ((i%2)==1);                 //  f  t  f  t  f  t  f  t  f  t

  myarray[mymask] *= valarray<int>(10,5);  //  0 10  2 30  4 50  6 70  8 90
  myarray[!mymask] = 0;                    //  0 10  0 30  0 50  0 70  0 90

  cout << "myarray:\n";
  for (size_t i=0; i<myarray.size(); ++i)
      cout << myarray[i] << ' ';
  cout << endl;

  return 0;
}

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

Заключение

Если вы действительно хотите пройти всетем не менее, вы должны начать смотреть на большие пушки (Blitz ++ и др.).

[1] они исторически были в центре внимания векторизованных наборов команд ЦП.Тем не менее, примечания als @jalf, SSE2 и выше также содержат целочисленные инструкции SIMD

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...