【问题标题】:Thrust vector transformation involving removing vector elements涉及去除向量元素的推力向量变换
【发布时间】:2013-01-15 04:02:22
【问题描述】:

我有一个推力 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)

我怎样才能正确地实现它?最好我想避免在 GPU 内存中分配一个新的向量来保存转换。我知道有处理这些类型的操作的推力模板函数,但我很难将它们串在一起。 Thrust 提供的东西可以做到这一点吗?

【问题讨论】:

  • 块的大小都一样吗?
  • 是的,块的大小都一样
  • 并行执行这个操作似乎很难,但如果你愿意分配临时存储,只需调用thrust::copy_if

标签: cuda thrust cublas bspline


【解决方案1】:

没有分配缓冲区内存意味着您必须保留复制顺序,不能并行以充分利用 GPU 硬件。

这是一个使用 Thrust 和缓冲内存的版本。

它需要 Thrust 1.6.0+,因为迭代器上使用了 lambda 表达式仿函数。

#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;
}

我认为由于使用了mod运算符%,上述版本可能无法达到最高性能。为了获得更高的性能,您可以考虑使用 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);

【讨论】:

  • 什么是newChunk、oldChunk和size? size 是块的数量还是每个 newChunk 的长度?
  • @user1522407 与推力代码中的定义相同
猜你喜欢
  • 2013-01-14
  • 2011-11-22
  • 1970-01-01
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多