C++ CUDA排序Z轴3D阵列C++/刺
我希望沿着z轴对大型3D阵列进行排序 示例阵列为X X Y X Z(1000x1000x5) 我想沿z轴排序,因此我将沿z轴对5个元素执行1000x1000排序 编辑更新:尝试使用下面的推力。它是功能性的,我会将输出存储回去,但这非常慢,因为我一次对每个(x,y)位置的5个元素进行排序:C++ CUDA排序Z轴3D阵列C++/刺,c++,sorting,cuda,thrust,C++,Sorting,Cuda,Thrust,我希望沿着z轴对大型3D阵列进行排序 示例阵列为X X Y X Z(1000x1000x5) 我想沿z轴排序,因此我将沿z轴对5个元素执行1000x1000排序 编辑更新:尝试使用下面的推力。它是功能性的,我会将输出存储回去,但这非常慢,因为我一次对每个(x,y)位置的5个元素进行排序: #include <stdio.h> #include <stdlib.h> #include <iostream> #include <thrust/device_
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <thrust/device_ptr.h>
#include <thrust/sort.h>
#include <thrust/gather.h>
#include <thrust/iterator/counting_iterator.h>
int main(){
int x = 1000, y = 1000, z = 5;
float*** unsorted_cube = new float** [x];
for (int i = 0; i < x; i++)
{
// Allocate memory blocks for
// rows of each 2D array
unsorted_cube[i] = new float* [y];
for (int j = 0; j < y; j++)
{
// Allocate memory blocks for
// columns of each 2D array
unsorted_cube[i][j] = new float[z];
}
}
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
unsorted_cube[i][j][0] = 4.0f;
unsorted_cube[i][j][1] = 3.0f;
unsorted_cube[i][j][2] = 1.0f;
unsorted_cube[i][j][3] = 5.0f;
unsorted_cube[i][j][4] = 2.0f;
}
}
for (int i = 0; i < 5; i++)
{
printf("unsorted_cube first 5 elements to sort at (0,0): %f\n", unsorted_cube[0][0][i]);
}
float* temp_input;
float* temp_output;
float* raw_ptr;
float raw_ptr_out[5];
cudaMalloc((void**)&raw_ptr, N_Size * sizeof(float));
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
temp_input[0] = unsorted_cube[i][j][0];
temp_input[1] = unsorted_cube[i][j][1];
temp_input[2] = unsorted_cube[i][j][2];
temp_input[3] = unsorted_cube[i][j][3];
temp_input[4] = unsorted_cube[i][j][4];
cudaMemcpy(raw_ptr, temp_input, 5 * sizeof(float), cudaMemcpyHostToDevice);
thrust::device_ptr<float> dev_ptr = thrust::device_pointer_cast(raw_ptr);
thrust::sort(dev_ptr, dev_ptr + 5);
thrust::host_vector<float> host_vec(5);
thrust::copy(dev_ptr, dev_ptr + 5, raw_ptr_out);
if (i == 0 && j == 0)
{
for (int i = 0; i < 5; i++)
{
temp_output[i] = raw_ptr_out[i];
}
printf("sorted_cube[0,0,0] : %f\n", temp_output[0]);
printf("sorted_cube[0,0,1] : %f\n", temp_output[1]);
printf("sorted_cube[0,0,2] : %f\n", temp_output[2]);
printf("sorted_cube[0,0,3] : %f\n", temp_output[3]);
printf("sorted_cube[0,0,4] : %f\n", temp_output[4]);
}
}
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
int x=1000,y=1000,z=5;
浮点***未排序的_立方体=新浮点**[x];
对于(int i=0;i
假设数据的格式是每个xy平面中的值在内存中是连续的:数据[((z*y_长度)+y)*x_长度+x]
(这也是在GPU上合并内存访问的最佳方式)
#包括
#包括
#包括
#包括
void sort_in_z_dir(推力::设备向量和数据,
int x_length,int y_length){//z_length==5
自动z_步幅=x_长度*y_长度;
推力:每个(
推力::make_-zip_迭代器(推力::make_元组(
data.begin(),
data.begin()+z_跨步,
data.begin()+2*z_步长,
data.begin()+3*z_步,
data.begin()+4*z_)),
推力::make_-zip_迭代器(推力::make_元组(
data.begin()+z_跨步,
data.begin()+2*z_步长,
data.begin()+3*z_步,
data.begin()+4*z_步长,
data.begin()+5*z_)),
[](推力::元组和值){
浮点本地_数据[5]={推力::获取(值),
推力::获取(值),
推力::获取(值),
推力::获取(值),
推力::获取(值)};
推力::排序(推力::顺序,本地_数据,本地_数据+5);
推力::获取(值)=本地_数据[0];
推力::获取(值)=本地_数据[1];
推力::获取(值)=本地_数据[2];
推力::获取(值)=本地_数据[3];
推力::获取(值)=本地_数据[4];
});
}
就硬编码z_长度
而言,此解决方案无疑非常难看。你可以使用一些C++模板——“魔术”来将<代码> ZyStime>代码变成模板参数,但是对于这个关于推力的答案,这似乎是多余的。
有关数组和元组之间接口的示例,请参见和
这个解决方案的好处是,根据排序算法本身,它应该是非常优化的性能。我不知道asch::sort
是否针对如此小的输入数组进行了优化,但您可以用我在评论中提出的任何自行编写的排序算法来代替它
如果您希望能够使用不同的z_长度
,而无需所有这些麻烦,您可能会更喜欢这种解决方案,它在全局内存中排序,这远远不是最优的,而且感觉有点粗糙,因为它几乎只在启动内核时使用推力。在这里,您希望以另一种方式对数据进行排序:data[((x*y_长度)+y)*z_长度+z]
#包括
#包括
#包括
#包括
void sort_in_z_dir_可选(推力::设备向量和数据,
整数x_长度、整数y_长度、整数z_长度){
int n_螺纹=x_长度*y_长度;
推力:每个(
推力::使_计数_迭代器(0),
推力::生成计数迭代器(n个线程),
[ddata=推力::原始指针转换(data.data()),z长度(intIDX){
推力::排序(推力::顺序,
ddata+z_长度*idx,
ddata+z_长度*(idx+1));
});
}
如果您同意将z_length
作为一个模板参数,那么这可能是一个结合了两方面优点的解决方案(如第一个示例中的数据格式):
#包括
#包括
#包括
#包括
模板
无效排序位于中间地面(推力::设备向量和数据,
整数x_长度