Кажется, что при создании нового вектора тяги все элементы равны 0 по умолчанию — я просто хочу подтвердить, что так будет всегда.
Если да, то есть ли способ обойти конструктор, ответственный за такое поведение, для дополнительной скорости (поскольку для некоторых векторов мне не нужно, чтобы они имели начальное значение, например, если их необработанные указатели передается в CUBLAS в качестве вывода)?
Как избежать построения элементов по умолчанию в Thrust::device_vector?
Ответы (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
Очень хорошо. Несмотря на то, что я уже писал перегрузки распределителя отладки для stl, я забыл, что последний вызов конструкции был здесь. Следовало продолжать копать. +1 :)
- person leander; 06.05.2013
На самом деле -- я в замешательстве. Я ошибаюсь в том, что
resize
в вашем примере связывается с insert
, который, в свою очередь, связывается с fill_insert
, который снова заканчивается uninitialized_fill_n
? Значит, вы все еще получаете копии, несмотря на то, что, возможно, проигнорировали construct
при настройке новой области storage_type
? ... очевидно, мне нужно пройти через это в отладчике, но я не вижу, как можно избежать возможного uninitialized_fill_n
из инициализированного по умолчанию/значения x
аргумента по умолчанию.
- person leander; 07.05.2013
Возможно, вам придется пройти через отладчик с самой последней версией Thrust. Это сложная отправка.
- person Jared Hoberock; 07.05.2013
Понял, извини. По какой-то причине мне просто не хватало версии 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