cuda中的双音排序会对某些值排序错误
Bitonic sorting in cuda misorders some values
我正在为一个更大的项目在CUDA上做一个排序算法,我决定实现一个Bitonic排序。我要排序的元素个数总是2的幂,实际上是512。我需要一个具有最终位置的数组,因为此方法将用于对表示另一个解的质量矩阵的数组进行排序。
fitness是我要排序的数组,numElements是元素的数量,而order最初是一个包含numElements位置的空数组,它将在一开始以这种方式填充:orden[i]=i
。事实上,秩序与这个问题无关,但我保留了它。
我的问题是一些值没有正确排序,直到现在我还无法弄清楚我有什么问题。
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <ctime>
#include <cuda.h>
#include <curand.h>
#include <curand_kernel.h>
#include <device_functions.h>
#include "float.h"
__global__ void sorting(int * orden, float * fitness, int numElements);
// Populating array with random values for testing purposes
__global__ void populate( curandState * state, float * fitness{
curandState localState = state[threadIdx.x];
int a = curand(&localState) % 500;
fitness[threadIdx.x] = a;
}
//Curand setup for the populate method
__global__ void setup_cuRand(curandState * state, unsigned long seed)
{
int id = threadIdx.x;
curand_init(seed, id, 0, &state[id]);
}
int main()
{
float * arrayx;
int numelements = 512;
int * orden;
float arrayCPU[512] = { 0 };
curandState * state;
cudaDeviceReset();
cudaSetDevice(0);
cudaMalloc(&state, numelements * sizeof(curandState));
cudaMalloc((void **)&arrayx, numelements*sizeof(float));
cudaMalloc((void **)&orden, numelements*sizeof(int));
setup_cuRand << <1, numelements >> >(state, unsigned(time(NULL)));
populate << <1, numelements >> > (state, arrayx);
cudaMemcpy(&arrayCPU, arrayx, numelements * sizeof(float), cudaMemcpyDeviceToHost);
for (int i = 0; i < numelements; i++)
printf("fitness[%i] = %fn", i, arrayCPU[i]);
sorting << <1, numelements >> >(orden, arrayx, numelements);
printf("nn");
cudaMemcpy(&arrayCPU, arrayx, numelements * sizeof(float), cudaMemcpyDeviceToHost);
for (int i = 0; i < numelements; i++)
printf("fitness[%i] = %fn", i, arrayCPU[i]);
cudaDeviceReset();
return 0;
}
__device__ bool isValid(float n){
return !(isnan(n) || isinf(n) || n != n || n <= FLT_MIN || n >= FLT_MAX);
}
__global__ void sorting(int * orden, float * fitness, int numElements){
int i = 0;
int j = 0;
float f = 0.0;
int aux = 0;
//initial orden registered (1, 2, 3...)
orden[threadIdx.x] = threadIdx.x;
//Logarithm on base 2 of numElements
for (i = 2; i <= numElements; i = i * 2){
// descending from i reducing to half each iteration
for (j = i; j >= 2; j = j / 2){
if (threadIdx.x % j < j / 2){
__syncthreads();
// ascending or descending consideration using (threadIdx.x % (i*2) < i)
if ((threadIdx.x % (i * 2) < i) && (fitness[threadIdx.x] > fitness[threadIdx.x + j / 2] || !isValid(fitness[threadIdx.x])) ||
((threadIdx.x % (i * 2) >= i) && (fitness[threadIdx.x] <= fitness[threadIdx.x + j / 2] || !isValid(fitness[threadIdx.x + j / 2])))){
aux = orden[threadIdx.x];
orden[threadIdx.x] = orden[threadIdx.x + j / 2];
orden[threadIdx.x + j / 2] = aux;
//Se reubican los fitness
f = fitness[threadIdx.x];
fitness[threadIdx.x] = fitness[threadIdx.x + j / 2];
fitness[threadIdx.x + j / 2] = f;
}
}
}
}
}
例如,随机执行时得到的输出:
随机执行
这是我的双音排序的表示:
双元排序模式,箭头指向比较最差值的位置
以下是我发现的问题:
-
在你发布的代码中,这不会编译:
__global__ void populate( curandState * state, float * fitness{ ^ missing close parenthesis
-
在这些
cudaMemcpy
语句中不需要取数组的地址:cudaMemcpy(&arrayCPU, arrayx, numelements * sizeof(float), cudaMemcpyDeviceToHost); .... cudaMemcpy(&arrayCPU, arrayx, numelements * sizeof(float), cudaMemcpyDeviceToHost);
数组名已经是数组的地址,所以我去掉了&号。如果使用动态分配的数组,这种用法将被打破。
-
你的
__syncthreads()
在这里的使用被打破了:
在条件语句中使用for (j = i; j >= 2; j = j / 2){ if (threadIdx.x % j < j / 2){ __syncthreads();
__syncthreads()
通常是不正确的,除非条件语句在线程块中统一求值。这在文档中有介绍。我们只需稍加改动就可以达到预期的效果:for (j = i; j >= 2; j = j / 2){ __syncthreads(); if (threadIdx.x % j < j / 2){
有了上面的改变,你的代码对我来说在大多数情况下都是正确运行的。如果您打算正确排序0(或任何负值),那么在有效性检查中使用FLT_MIN
也是有问题的。一般来说,FLT_MIN
是一个非常小的数字,接近于零。如果你认为这是一个很大的负数,它不是。因此,零是随机数生成器的可能输出,它不会被正确排序。我将把这个问题留给你来解决,它应该很简单,但这取决于你最终想要实现什么。(如果您只想对正的非零浮点值进行排序,测试可能是可以的,但在这种情况下,您的随机数生成器可能会返回0。)
- 将图形表示为unordered_map<字符串、向量>时拓扑排序错误<string>
- C++插入排序错误功能不起作用
- C++ 换行符上的合并排序错误中断
- C++ 快速排序错误
- 合并排序错误 - 表达式必须具有常量值
- C 插入排序错误
- 对向量 OS 字符串进行排序 C++ 错误 C2784 无法推断模板参数
- 递归合并排序错误
- 使用C++的快速排序错误
- std::使用自定义类排序错误
- 使用类在 C++ 中快速排序错误
- 数组中的函数排序错误
- 插入排序错误
- C++部分排序错误
- sort对某些值排序错误
- 针对c++ STL的自定义比较器排序错误预期-在')'标记之前的主表达式
- 气泡排序错误LNK2019
- 链表的归并排序错误
- 快速排序错误:变量周围的堆栈已损坏
- 排序错误:不允许使用类型名称