Как избежать построения элементов по умолчанию в 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) Detail::vector_base::resize (целое число без знака new_size) - person leander; 07.05.2013