我有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中的矩阵列?
我的矩阵存储在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) 对于我的应用程序,我必须处理一堆对象(比如ints),这些对象随后被分割并分类成更小的桶.为此,我将元素存储在一个连续的数组中
arr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14...}
Run Code Online (Sandbox Code Playgroud)
并且关于桶(子列表)的信息由相应桶中的第一个元素的偏移量和子列表的长度给出.
所以,例如,给定
offsets = {0,3,8,..}
sublist_lengths = {3,5,2,...}
Run Code Online (Sandbox Code Playgroud)
会导致以下分裂:
0 1 2 || 3 4 5 6 7 || 8 9 || ...
Run Code Online (Sandbox Code Playgroud)
我正在寻找的只是使用自定义内核或thrust库在桶上运行算法(如减少)的一种通用且有效的方法.总结水桶应该给:
3 || 25 || 17 || ...
Run Code Online (Sandbox Code Playgroud)
我想出了什么:
选项1:自定义内核需要相当多的修补,复制到共享内存,正确选择块和网格大小以及自己的算法实现,如扫描,减少等.此外,每个操作都需要自己定制核心.总的来说,我很清楚如何做到这一点,但在thrust过去几天使用后,我的印象是可能有更聪明的方式
选项2:从偏移量({0,0,0,1,1,1,1,1,2,2,3,...}在上面的例子中)生成一个键数组并使用thrust::reduce_by_key.不过,我不喜欢额外的列表生成.
选项3:thrust::transform_iterator与...一起使用thrust::counting_iterator以生成上面给出的密钥列表.不幸的是,我无法想出一个实现,它不需要将索引增加到设备上的偏移列表,并且会破坏并行性.
实现这一目标最理智的方式是什么?
我试图用来thrust::transform减少a的每个元素的常量值device_vector.如您所见,最后一行不完整.我试图从所有元素减去常数,fLowestVal但不知道究竟是多少.
thrust::device_ptr<float> pWrapper(p);
thrust::device_vector<float> dVector(pWrapper, pWrapper + MAXX * MAXY);
float fLowestVal = *thrust::min_element(dVector.begin(), dVector.end(),thrust::minimum<float>());
// XXX What goes here?
thrust::transform(...);
Run Code Online (Sandbox Code Playgroud)
另一个问题:一旦我对其进行了更改device_vector,更改是否也适用于p阵列?
谢谢!
我想在映射内存上使用零拷贝cudaHostGetDevicePointer.我可以使用thrust::host_vector或者必须使用cudaHostAlloc(...,cudaHostAllocMapped)?
或者它是否更容易使用Thrust?
我是一名CUDA初学者并正在阅读一些推力教程.我写了一个简单但非常有组织的代码并试图找出推力的加速度.(这个想法是否正确?).我尝试通过在cpu上添加数组并在gpu上添加device_vector,将两个向量(10000000 int)添加到另一个向量.
这是事情:
#include <iostream>
#include "cuda.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#define N 10000000
int main(void)
{
float time_cpu;
float time_gpu;
int *a = new int[N];
int *b = new int[N];
int *c = new int[N];
for(int i=0;i<N;i++)
{
a[i]=i;
b[i]=i*i;
}
clock_t start_cpu,stop_cpu;
start_cpu=clock();
for(int i=0;i<N;i++)
{
c[i]=a[i]+b[i];
}
stop_cpu=clock();
time_cpu=(double)(stop_cpu-start_cpu)/CLOCKS_PER_SEC*1000;
std::cout<<"Time to generate (CPU):"<<time_cpu<<std::endl;
thrust::device_vector<int> X(N);
thrust::device_vector<int> Y(N);
thrust::device_vector<int> Z(N);
for(int i=0;i<N;i++)
{
X[i]=i;
Y[i]=i*i;
}
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);
thrust::transform(X.begin(), X.end(), …Run Code Online (Sandbox Code Playgroud) 我有一个相当简单的问题,但我无法找到一个优雅的解决方案.
我有一个Thrust代码,它生成c包含值的相同大小的向量.假设这些c向量中的每一个都有一个索引.我想为每个向量位置获取c值为最低的向量的索引:
例:
C0 = (0,10,20,3,40)
C1 = (1,2 ,3 ,5,10)
Run Code Online (Sandbox Code Playgroud)
我会得到一个包含C具有最低值的向量索引的向量:
result = (0,1 ,1 ,0,1)
Run Code Online (Sandbox Code Playgroud)
我已经考虑过使用推力zip迭代器来做这件事,但是已经遇到了问题:我可以压缩所有c向量并实现任意转换,它接受一个元组并返回其最低值的索引,但是:
10元素,并且可以存在比10 c矢量更多的元素.然后我考虑这样做:不是使用c单独的向量,而是将它们全部附加到单个向量中C,然后生成引用位置的键并按键执行稳定排序,这将从同一位置重新组合向量条目.在示例中,将给出:
C = (0,10,20,3,40,1,2,3,5,10)
keys = (0,1 ,2 ,3,4 ,0,1,2,3,4 )
after stable sort by key:
output = (0,1,10,2,20,3,3,5,40,10)
keys = (0,0,1 ,1,2 ,2,3,3,4 ,4 )
Run Code Online (Sandbox Code Playgroud)
然后使用向量中的位置生成键,使用向量的索引压缩输出,c然后使用自定义函数执行按键缩减,对于每个缩减,输出具有最低值的索引.在示例中:
input = (0,1,10,2,20,3,3,5,40,10)
indexes= (0,1,0 ,1,0 ,1,0,1,0 ,1)
keys = (0,0,1 ,1,2 …Run Code Online (Sandbox Code Playgroud) 我正在使用在CUDA上运行的Marching Cubes算法从体积数据生成网格.
我试过保存网格并以3种方式渲染它.
V0x, V0y, V0z, N0x, N0y, N0z, V1x, V1y, V1z, N1x, N1y, N1z, ...
并使用它绘制glDrawArrays().
VBO中的冗余顶点,每个多维数据集的冗余顶点,无索引.
thrust::sort()和thrust::unique()删除冗余顶点,使用计算索引thrust::lower_bound().将结果保存到映射到CUDA的OpenGL VBO/IBO.使用绘制模型glDrawElements().VBO中没有冗余顶点,生成指数.
glDrawElements().VBO中的冗余顶点,每个多维数据集的唯一顶点,每个多维数据集的生成索引
现在我得到的相同数据集的FPS是相同的ISO-Value`
Method 1 : 92 FPS, 30,647,016 Verts, 0 Indices
Method 2 : 122 FPS, 6,578,066 Verts, 30,647,016 Indices
Method 3 : 140 FPS, 20,349,880 Verts, 30,647,016 Indices
Run Code Online (Sandbox Code Playgroud)
即使方法2产生最少数量的顶点,FPS也很低.我相信这是因为索引的顺序可以最大限度地减少GPU缓存的使用.方法3的索引顺序获得更高的GPU缓存使用率,因此FPS更高.
如何修改/修改方法2以获得更高的FPS?
我正在尝试编译并运行一个简单的 Cuda/thrust 程序,当扩展名是 时它可以工作,.cu但当源扩展名是.cpp. 我已经在 cmake 中应用了 cpp 文件所需的更改,但我得到了
错误:静态断言失败:此系统未实现 THRUST_STATIC_ASSERT_MSG
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(thrust_test LANGUAGES CXX CUDA)
find_package(CUDA 10.0 REQUIRED)
message(STATUS "CUDA ${CUDA_VERSION_STRING} at ${CUDA_TOOLKIT_ROOT_DIR}")
set(CUDA_LINK_LIBRARIES_KEYWORD PUBLIC)
include_directories(${CUDA_INCLUDE_DIRS})
link_directories(${CUDA_LIBRARY_DIRS})
set(CMAKE_CUDA_STANDARD 14)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CUDA_SEPARABLE_COMPILATION ON)
set_source_files_properties(
main.cpp
PROPERTIES
CUDA_SOURCE_PROPERTY_FORMAT
OBJ)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} ${CUDA_LIBRARIES})
Run Code Online (Sandbox Code Playgroud)
和main.cpp:
__host__
__device__
int foo() {
// generate random data serially
thrust::host_vector<int> h_vec(100);
std::generate(h_vec.begin(), h_vec.end(), rand);
// transfer to device and compute sum
thrust::device_vector<int> d_vec = h_vec;
return thrust::reduce(d_vec.begin(), d_vec.end(), 0, …Run Code Online (Sandbox Code Playgroud)