使用Thrust对静态分配的数组进行排序

时间:2016-01-21 19:14:07

标签: c++ sorting cuda thrust

在我的代码中,我在全局内存中有一个静态分配的数组(即使用__device__分配),我想使用thrust::sort排序,但这是无效的。本主题的所有示例都使用CUDA运行时分配的数组(使用cudaMalloc)。有什么方法可以对静态分配的数组进行排序吗?

我猜这与静态无法从主机访问的静态分配内存有关。使用cudaMalloc - 分配的数组,它工作正常。但是,我想避免使用这种类型的分配,因为静态分配允许更容易地从设备代码访问数据(不是吗?)。

最小(不是)工作示例:

#include <stdio.h>
#include <thrust/device_ptr.h>
#include <thrust/sort.h>

#define N 4

typedef struct element {
  int key;
  int value;
  __host__ __device__ bool operator<(element e) const
  { return key > e.key; }
} element;

__device__ element array[N];

__global__ void init() {
  for (int i = 0; i < N; ++i) {
    array[N - i - 1].key = i;
  }
}

__global__ void print_array() {
  for (int i = 0; i < N; ++i) {
    printf("%d ", array[i].key);
  }
  printf("\n");
}

int main(void) {
  thrust::device_ptr<element> array_first(array);

  init<<<1,1>>>();

  printf("unsorted: ");
  print_array<<<1, 1>>>();
  cudaDeviceSynchronize();

  thrust::sort(array_first, array_first + N);

  printf("sorted: ");
  print_array<<<1, 1>>>();
  cudaDeviceSynchronize();
}

2 个答案:

答案 0 :(得分:2)

使用declare class Meteor { isClient: boolean; } cudaGetSymbolAddress函数中获取array变量的地址:

__host__

这是完整的程序:

void* array_ptr = 0;
cudaGetSymbolAddress(&array_ptr, array);
thrust::device_ptr<element> array_first(reinterpret_cast<element*>(array_ptr));

这是我系统上的输出:

#include <stdio.h>
#include <thrust/device_ptr.h>
#include <thrust/sort.h>

#define N 4

typedef struct element {
  int key;
  int value;
  __host__ __device__ bool operator<(element e) const
  { return key > e.key; }
} element;

__device__ element array[N];

__global__ void init() {
  for (int i = 0; i < N; ++i) {
    array[N - i - 1].key = i;
  }
}

__global__ void print_array() {
  for (int i = 0; i < N; ++i) {
    printf("%d ", array[i].key);
  }
  printf("\n");
}

int main(void) {
  cudaError_t error;

  void* array_ptr = 0;
  if(error = cudaGetSymbolAddress(&array_ptr, array))
  {
    throw thrust::system_error(error, thrust::cuda_category());
  }

  thrust::device_ptr<element> array_first(reinterpret_cast<element*>(array_ptr));

  init<<<1,1>>>();

  printf("unsorted: ");
  print_array<<<1, 1>>>();

  if(error = cudaDeviceSynchronize())
  {
    throw thrust::system_error(error, thrust::cuda_category());
  }

  thrust::sort(array_first, array_first + N);

  if(error = cudaDeviceSynchronize())
  {
    throw thrust::system_error(error, thrust::cuda_category());
  }

  printf("sorted: ");
  print_array<<<1, 1>>>();

  if(error = cudaDeviceSynchronize())
  {
    throw thrust::system_error(error, thrust::cuda_category());
  }

  return 0;
}

排序的输出与未排序的输出相同,但我想这是有意的,因为数据的生成方式和$ nvcc test.cu -run unsorted: 3 2 1 0 sorted: 3 2 1 0 的定义。

答案 1 :(得分:2)

此:

__device__ element array[N];

...

thrust::device_ptr<element> array_first(array);

是非法的。在 host 代码中,array是主机地址,无法传递给设备代码。做这样的事情:

element* array_d;
cudaGetSymbolAddress((void **)&array_d, array);
thrust::device_ptr<element> array_first(array_d);

即。您需要使用cudaGetSymbolAddress在运行时从GPU上下文中读取地址,然后您可以在GPU代码中使用该调用的结果。