Преобразование вектора тяги с удалением векторных элементов
У меня есть тяга device_vector, разделенная на порции по 100 (но в целом смежные с памятью GPU), и я хочу удалить последние 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, способное сделать это?
1 ответ
Отсутствие выделения буфера mem означает, что вы должны сохранить порядок копирования, который не может быть распараллелен для полного использования аппаратного обеспечения графического процессора.
Вот версия для этого с использованием Thrust с буфером mem.
Требуется 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);