Thrust是开始编程CUDA的惊人包装器.我想知道有什么东西要用NVIDIA CUFFT封装,或者我们需要自己实现?
最近我一直在使用推力很多.我注意到为了使用推力,必须始终将数据从cpu内存复制到gpu内存.
我们来看下面的例子:
int foo(int *foo)
{
host_vector<int> m(foo, foo+ 100000);
device_vector<int> s = m;
}
Run Code Online (Sandbox Code Playgroud)
我不太确定host_vector构造函数是如何工作的,但似乎我正在复制初始数据,来自*foo,两次 - 初始化时一次到host_vector,另一次device_vector初始化时.是否有更好的方法从cpu复制到gpu而不制作中间数据副本?我知道我可以device_ptr用作包装器,但这仍然无法解决我的问题.
谢谢!
Thrust库可用于对数据进行排序.调用可能看起来像这样(带有键和值向量):
thrust::sort_by_key(d_keys.begin(), d_keys.end(), d_values.begin());
Run Code Online (Sandbox Code Playgroud)
称为在CPU上,以d_keys及d_values在CPU存储器是; 并且大部分执行都发生在GPU上.
但是,我的数据已经在GPU上?如何使用Thrust库直接在GPU上执行高效排序,即sort_by_key从内核调用函数?
此外,我的数据包括或者是unsigned long long int或者unsigned int始终是数据的键
unsigned int.我应该如何对这些类型进行推力调用?
似乎在创建一个新的Thrust向量时,默认情况下所有元素都是0 - 我只是想确认这种情况总是如此.
如果是这样,是否还有一种方法绕过负责此行为的构造函数以获得额外的速度(因为对于某些向量,我不需要它们具有初始值,例如,如果它们的原始指针作为输出传递给CUBLAS) ?
我有一个需要在设备上多次引用的float数组,所以我认为存储它的最佳位置是__ constant __ memory(使用此引用).数组(或向量)需要在初始化时在运行时写入一次,但是由多个不同的函数读取数百万次,因此每次函数调用向内核的不断复制似乎是一个坏主意.
const int n = 32;
__constant__ float dev_x[n]; //the array in question
struct struct_max : public thrust::unary_function<float,float> {
float C;
struct_max(float _C) : C(_C) {}
__host__ __device__ float operator()(const float& x) const { return fmax(x,C);}
};
void foo(const thrust::host_vector<float> &, const float &);
int main() {
thrust::host_vector<float> x(n);
//magic happens populate x
cudaMemcpyToSymbol(dev_x,x.data(),n*sizeof(float));
foo(x,0.0);
return(0);
}
void foo(const thrust::host_vector<float> &input_host_x, const float &x0) {
thrust::device_vector<float> dev_sol(n);
thrust::host_vector<float> host_sol(n);
//this method works fine, but the …Run Code Online (Sandbox Code Playgroud) 我有3相同大小的数组(超过300.000元素).一个浮点数和两个索引数组.所以,对于每个号码我都有2ID.
所有3阵列都已经在GPU全局内存中.我想相应地将所有数字与他们的ID排序.
有什么方法可以使用Thrust库来完成这项任务吗?有没有比推力图书馆更好的方法?
当然,我不喜欢将它们复制到主机内存中几次.顺便说一句,他们的数组不是向量.
感谢您的帮助.
暂时的解决方案,但这是非常缓慢的.它需要几4秒钟,我的数组大小按顺序排列300000
thrust::device_ptr<float> keys(afterSum);
thrust::device_ptr<int> vals0(d_index);
thrust::device_ptr<int> vals1(blockId);
thrust::device_vector<int> sortedIndex(numElements);
thrust::device_vector<int> sortedBlockId(numElements);
thrust::counting_iterator<int> iter(0);
thrust::device_vector<int> indices(numElements);
thrust::copy(iter, iter + indices.size(), indices.begin());
thrust::sort_by_key(keys, keys + numElements , indices.begin());
thrust::gather(indices.begin(), indices.end(), vals0, sortedIndex.begin());
thrust::gather(indices.begin(), indices.end(), vals1, sortedBlockId.begin());
thrust::host_vector<int> h_sortedIndex=sortedIndex;
thrust::host_vector<int> h_sortedBlockId=sortedBlockId;
Run Code Online (Sandbox Code Playgroud) 我正在将OpenCV用于计算机视觉应用.我想在GPU上加速一些矩阵运算(矩阵相当大),并且如果可能的话,希望避免直接在CUDA C中进行编码.OpenCV 2.4.1具有许多GPU加速功能.他们的体验表现如何?我最好还是使用另一个库(例如Thrust)吗?
EDIT 示例应用:计算GPU上的平方欧几里德距离矩阵.目前,我在Matlab中使用并行计算工具箱(PCT)进行的GPU加速(和矢量化)实现比使用OpenCV的C++实现快5到10倍.
Matlab实现:
function K = sqEuclideanDist(P_cpu,Q_cpu)
% Vectorized method to compute pairwise squared Euclidean distance on GPU
% Returns K(i,j) = (P(i,:) - Q(j,:))'*(P(i,:) - Q(j,:))
P_gpu = gpuArray(P_cpu);
Q_gpu = gpuArray(Q_cpu);
[nP, d] = size(P_gpu);
[nQ, d] = size(Q_gpu);
pmag = sum(P_gpu .* P_gpu, 2);
qmag = sum(Q_gpu .* Q_gpu, 2);
% note that K is on GPU
K = ones(nP,1)*qmag' + pmag*ones(1,nQ) - 2*P_gpu*Q_gpu';
end
Run Code Online (Sandbox Code Playgroud)
更新这是另一个完成相同的Matlab实现(感谢/sf/answers/544202641/).但它仅在CPU上运行,因为bsxfunPCT不支持.仍然在寻找C++替代品.
function …Run Code Online (Sandbox Code Playgroud) 如何使用CUDA并行地从数组中有效地删除零值.有关零值数量的信息可以提前获得,这可以简化此任务.
在复制到结果数组时,数字在源数组中保持有序排列非常重要.
例:
该数组将例如包含以下值:[0,0,19,7,0,3,5,0,0,1]以及5个值为零的附加信息.然后,期望的最终结果将是包含以下内容的另一个数组:[19,7,3,5,1]
如何有效地规范化CUDA中的矩阵列?
我的矩阵存储在column-major中,典型大小为2000x200.
该操作可以用以下matlab代码表示.
A = rand(2000,200);
A = exp(A);
A = A./repmat(sum(A,1), [size(A,1) 1]);
Run Code Online (Sandbox Code Playgroud)
这可以通过Thrust,cuBLAS和/或cuNPP有效地完成吗?
包括4个内核的快速实现如下所示.
想知道这些是否可以在1或2个内核中完成以提高性能,尤其是对于由cublasDgemv()实现的列求和步骤.
#include <cuda.h>
#include <curand.h>
#include <cublas_v2.h>
#include <thrust/device_vector.h>
#include <thrust/device_ptr.h>
#include <thrust/transform.h>
#include <thrust/iterator/constant_iterator.h>
#include <math.h>
struct Exp
{
__host__ __device__ void operator()(double& x)
{
x = exp(x);
}
};
struct Inv
{
__host__ __device__ void operator()(double& x)
{
x = (double) 1.0 / x;
}
};
int main()
{
cudaDeviceSetCacheConfig(cudaFuncCachePreferShared);
cublasHandle_t hd;
curandGenerator_t rng;
cublasCreate(&hd);
curandCreateGenerator(&rng, CURAND_RNG_PSEUDO_DEFAULT);
const size_t m = 2000, …Run Code Online (Sandbox Code Playgroud) 我想使用推力将内存从主机复制到设备
thrust::host_vector<float> h_vec(1 << 28);
thrust::device_vector<float> d_vec(1 << 28);
thrust::copy(h_vec.begin(), h_vec.end(), d_vec.begin());
Run Code Online (Sandbox Code Playgroud)
使用CUDA流类似于使用流将内存从设备复制到设备的方式:
cudaStream_t s;
cudaStreamCreate(&s);
thrust::device_vector<float> d_vec1(1 << 28), d_vec2(1 << 28);
thrust::copy(thrust::cuda::par.on(s), d_vec1.begin(), d_vec1.end(), d_vec2.begin());
cudaStreamSynchronize(s);
cudaStreamDestroy(s);
Run Code Online (Sandbox Code Playgroud)
问题是我无法将执行策略设置为CUDA以在从主机复制到设备时指定流,因为在这种情况下,推力会假设两个向量都存储在设备上.有办法解决这个问题吗?我正在使用github的最新推力版本(它在version.h文件中显示为1.8).