Нахождение максимального значения элемента И его положение с помощью CUDA Thrust - PullRequest
14 голосов
/ 10 октября 2011

Как получить не только значение, но и положение максимального (минимального) элемента (res.val и res.pos)?

thrust::host_vector<float> h_vec(100);
thrust::generate(h_vec.begin(), h_vec.end(), rand);
thrust::device_vector<float> d_vec = h_vec;

T res = -1;
res = thrust::reduce(d_vec.begin(), d_vec.end(), res, thrust::maximum<T>());

Ответы [ 2 ]

17 голосов
/ 10 октября 2011

Не используйте thrust::reduce. Используйте thrust::max_element (thrust::min_element) в thrust/extrema.h:

thrust::host_vector<float> h_vec(100);
thrust::generate(h_vec.begin(), h_vec.end(), rand);
thrust::device_vector<float> d_vec = h_vec;

thrust::device_vector<float>::iterator iter =
  thrust::max_element(d_vec.begin(), d_vec.end());

unsigned int position = iter - d_vec.begin();
float max_val = *iter;

std::cout << "The maximum value is " << max_val << " at position " << position << std::endl;

Будьте внимательны при передаче пустого диапазона в max_element - вы не сможете безопасно разыменовать результат.

6 голосов
/ 19 февраля 2015

Джаред Хоберок уже удовлетворительно ответил на этот вопрос. Ниже я хочу представить небольшое изменение, чтобы учесть общий случай, когда массив был выделен cudaMalloc, а не через device_vector контейнер.

Идея состоит в том, чтобы обернуть device_pointer dev_ptr вокруг cudaMalloc 'ed необработанного указателя, приведя вывод min_element (я рассматриваю минимум вместо максимума без потери общности) к device_pointer min_ptr, а затем найти минимальное значение как min_ptr[0], а позицию - &min_ptr[0] - &dev_ptr[0].

#include "cuda_runtime.h"
#include "device_launch_paraMeters.h"

#include <thrust\device_vector.h>
#include <thrust/extrema.h>

/***********************/
/* CUDA ERROR CHECKING */
/***********************/
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true)
{
   if (code != cudaSuccess) 
   {
      fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
      if (abort) exit(code);
   }
}

/********/
/* MAIN */
/********/
int main() {

    srand(time(NULL));

    const int N = 10;

    float *h_vec = (float *)malloc(N * sizeof(float));
    for (int i=0; i<N; i++) {
        h_vec[i] = rand() / (float)(RAND_MAX);
        printf("h_vec[%i] = %f\n", i, h_vec[i]);
    }

    float *d_vec; gpuErrchk(cudaMalloc((void**)&d_vec, N * sizeof(float)));
    gpuErrchk(cudaMemcpy(d_vec, h_vec, N * sizeof(float), cudaMemcpyHostToDevice));

    thrust::device_ptr<float> dev_ptr = thrust::device_pointer_cast(d_vec);

    thrust::device_ptr<float> min_ptr = thrust::min_element(dev_ptr, dev_ptr + N);

    float min_value = min_ptr[0];
    printf("\nMininum value = %f\n", min_value);
    printf("Position = %i\n", &min_ptr[0] - &dev_ptr[0]);

}
...