Как да избегнем конструкцията по подразбиране на елементи в thrust::device_vector?

  1. Изглежда, когато създавате нов вектор на тласък, всички елементи са 0 по подразбиране - просто искам да потвърдя, че това винаги ще бъде така.

  2. Ако е така, има ли също начин за заобикаляне на конструктора, отговорен за това поведение, за допълнителна скорост (тъй като за някои вектори не е необходимо те да имат начална стойност, напр. ако техните необработени указатели се предадено на CUBLAS като изход)?


person mchen    schedule 05.05.2013    source източник


Отговори (1)


thrust::device_vector конструира елементите, които съдържа, като използва предоставения си разпределител, точно както std::vector. Възможно е да се контролира какво прави разпределителят, когато векторът поиска от него да конструира елемент.

Използвайте персонализиран разпределител, за да избегнете инициализация по подразбиране на векторни елементи:

// uninitialized_allocator is an allocator which
// derives from device_allocator and which has a
// no-op construct member function
template<typename T>
  struct uninitialized_allocator
    : thrust::device_malloc_allocator<T>
{
  // note that construct is annotated as
  // a __host__ __device__ function
  __host__ __device__
  void construct(T *p)
  {
    // no-op
  }
};

// to make a device_vector which does not initialize its elements,
// use uninitialized_allocator as the 2nd template parameter
typedef thrust::device_vector<float, uninitialized_allocator<float> > uninitialized_vector;

Все още ще поемате разходите за стартиране на ядрото, за да извикате uninitialized_allocator::construct, но това ядро ​​ще бъде без операция и ще се оттегли бързо. Това, от което наистина се интересувате, е избягването на честотната лента на паметта, необходима за запълване на масива, което прави това решение.

Има пълен примерен код тук.

Имайте предвид, че тази техника изисква Thrust 1.7 или по-добра.

person Jared Hoberock    schedule 06.05.2013
comment
Много добре. Въпреки че писах претоварвания на алокатора за отстраняване на грешки за stl преди, забравих, че последното извикване на конструкция беше тук. Трябваше да продължи да копае. +1 :) - person leander; 06.05.2013
comment
Всъщност - объркан съм. Греша ли в това, че resize във вашия пример се свързва с insert, което на свой ред се свързва с fill_insert, което отново завършва в uninitialized_fill_n? Значи все още получавате копия, въпреки че вероятно сте пренебрегнали construct при настройването на новата storage_type област там? ...очевидно трябва да премина през това в програма за отстраняване на грешки, но не виждам как може да се избегне евентуалното uninitialized_fill_n от инициализираната по подразбиране/стойност x аргумент по подразбиране. - person leander; 07.05.2013
comment
Може да се наложи да преминете през дебъгер с най-новия Thrust. Това е сложно изпращане. - person Jared Hoberock; 07.05.2013
comment
Разбрах, съжалявам. По някаква причина просто ми липсваше версията с един аргумент на resize() във vector_base.inl. Извинете за безпокойството! За всеки, който гледа заедно, стекът е: (1) detail::contiguous_storage::contiguous_storage(unsigned int n, const uninitialized_allocator‹float› & alloc) (2) detail::vector_base::append(unsigned int n) (3) детайл :: векторна_база :: преоразмеряване (неподписан int нов_размер) - person leander; 07.05.2013