#cuda #thrust
#cuda #тяга
Вопрос:
Как мне получить не только значение, но и положение максимального (минимального) элемента ( 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>());
Ответ №1:
Не используйте 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
— вы не сможете безопасно разыменовать результат.
Комментарии:
1. Как можно разыменовать итератор устройства в хосте? Есть ли у thrust неявный оператор разыменования, который выполняет cudaMemcpy?
Ответ №2:
Джаред Хоберок уже удовлетворительно ответил на этот вопрос. Ниже я хочу представить небольшое изменение, учитывающее общий случай, когда массив был выделен, cudaMalloc
а не через device_vector
контейнер.
Идея состоит в том, чтобы обернуть a device_pointer
dev_ptr
вокруг указателя cudaMalloc
‘ed raw, преобразуя выходные min_element
данные (я рассматриваю минимум вместо максимума без какой-либо потери общности) в a device_pointer
min_ptr
, а затем найти минимальное значение as min_ptr[0]
и позицию by amp;min_ptr[0] - amp;dev_ptr[0]
.
#include "cuda_runtime.h"
#include "device_launch_paraMeters.h"
#include <thrustdevice_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 %dn", 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] = %fn", i, h_vec[i]);
}
float *d_vec; gpuErrchk(cudaMalloc((void**)amp;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 = %fn", min_value);
printf("Position = %in", amp;min_ptr[0] - amp;dev_ptr[0]);
}