Преобразование вектора тяги с удалением элементов вектора

У меня есть тяга device_vector, разделенная на куски по 100 (но полностью смежные в памяти графического процессора), и я хочу удалить последние 5 элементов каждого фрагмента, не перераспределяя новый device_vector для его копирования.

// Layout in memory before (number of elements in each contiguous subblock listed):
// [   95   | 5 ][   95   | 5 ][   95   | 5 ]........

// Layout in memory after cutting out the last 5 of each chunk (number of elements listed)
// [  95  ][  95  ][  95  ].........

thrust::device_vector v;
// call some function on v;

// so elements 95-99, 195-99, 295-299, etc are removed (assuming 0-based indexing)

Как я могу правильно реализовать это? Предпочтительно, чтобы я не выделял новый вектор в памяти графического процессора для сохранения преобразования. Я понимаю, что существуют шаблонные функции Thrust для работы с такого рода операциями, но у меня возникают проблемы с их объединением. Есть ли что-то, что может сделать Thrust?


person user1522407    schedule 31.01.2013    source источник
comment
Кусочки все одного размера?   -  person talonmies    schedule 31.01.2013
comment
да, кусочки все одного размера   -  person user1522407    schedule 31.01.2013
comment
Кажется сложным выполнять эту операцию на месте параллельно, но если вы хотите выделить временное хранилище, это просто вызов thrust::copy_if.   -  person Jared Hoberock    schedule 31.01.2013


Ответы (1)


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

Вот версия для этого с помощью Thrust с буферной памятью.

Для этого требуется Thrust 1.6.0+, так как функтор лямбда-выражения используется в итераторах.

#include "thrust/device_vector.h"
#include "thrust/iterator/counting_iterator.h"
#include "thrust/iterator/permutation_iterator.h"
#include "thrust/iterator/transform_iterator.h"
#include "thrust/copy.h"
#include "thrust/functional.h"

using namespace thrust::placeholders;

int main()
{
    const int oldChunk = 100, newChunk = 95;
    const int size = 10000;

    thrust::device_vector<float> v(
            thrust::counting_iterator<float>(0),
            thrust::counting_iterator<float>(0) + oldChunk * size);
    thrust::device_vector<float> buf(newChunk * size);

    thrust::copy(
            thrust::make_permutation_iterator(
                    v.begin(),
                    thrust::make_transform_iterator(
                            thrust::counting_iterator<int>(0),
                            _1 / newChunk * oldChunk + _1 % newChunk)),
            thrust::make_permutation_iterator(
                    v.begin(),
                    thrust::make_transform_iterator(
                            thrust::counting_iterator<int>(0),
                            _1 / newChunk * oldChunk + _1 % newChunk))
                    + buf.size(),
            buf.begin());

    return 0;
}

Я думаю, что приведенная выше версия может не достичь максимальной производительности из-за использования оператора мода %. Для повышения производительности вы можете использовать функцию cuBLAS cublas_geam().

float alpha = 1;
float beta = 0;
cublasSgeam(handle, CUBLAS_OP_N, CUBLAS_OP_N,
            newChunk, size,
            &alpha,
            thrust::raw_pointer_cast(&v[0]), oldChunk,
            &beta,
            thrust::raw_pointer_cast(&v[0]), oldChunk,
            thrust::raw_pointer_cast(&buf[0]), newChunk);
person kangshiyin    schedule 31.01.2013
comment
Что такое newChunk, oldChunk и размер? Является ли размер количеством фрагментов или длиной каждого нового фрагмента? - person user1522407; 01.02.2013
comment
@user1522407 user1522407 Они совпадают с определением в коде тяги. - person kangshiyin; 01.02.2013