Этим вопрос связан с существующим вопросом, публикуемым мной пару недель назад: TERCOM algorithm - Changing from single thread to multiple threads in CUDAНахождение минимума между потоками
Кратко объяснил, каждый из потоков в ядре вычисляет MAD значения, и я хотел бы знать, минимум и его местоположение.
Я пытался использовать atomicMin как этот
__global__ void kernel (int m, int n, int h, int N, int *f, float heading, float *measurements, int *global_min)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int idy = blockIdx.y * blockDim.y + threadIdx.y;
float MAD=0;
float pos[2];
float theta=heading*(PI/180);
float fval = 0;
// Calculate how much to move in x and y direction
float offset_x = h*cos(theta);
float offset_y = -h*sin(theta);
//Calculate Mean Absolute Difference
if(idx < n && idy < m)
{
for(float g=0; g<N; g++)
{
float fval = tex2D (tex, idx+(g-2)*offset_x+0.5f, idy+(g-2)*offset_y+0.5f);
MAD += abs(measurements[(int)g]-fval);
}
}
cuPrintf("%.2f \n",MAD);
atomicMin(global_min, MAD);
pos[0]=idx;
pos[1]=idy;
f[0]=*global_min;
f[1]=pos[0];
f[2]=pos[1];
}
И производить правильный результат, но atomicMin не в состоянии найти местоположение минимума.
Я также попытался использовать библиотеку упорную
__global__ void kernel (int m, int n, int h, int N, int *f, float heading, float *measurements, int *global_min, float *dev_MAD)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
int idy = blockIdx.y * blockDim.y + threadIdx.y;
float theta=heading*(PI/180);
float fval = 0;
// Calculate how much to move in x and y direction
float offset_x = h*cos(theta);
float offset_y = -h*sin(theta);
//Calculate Mean Absolute Difference
if(idx < n && idy < m)
{
for(float g=0; g<N; g++)
{
float fval = tex2D (tex, idx+(g-2)*offset_x+0.5f, idy+(g-2)*offset_y+0.5f);
*dev_MAD += abs(measurements[(int)g]-fval);
}
}
cuPrintf("%.2f \n",MAD);
}
и вызов ядра, как этот
kernel <<< dimGrid,dimBlock >>> (m, n, h, N, dev_results, heading, dev_measurements, global_min, dev_MAD);
thrust::device_ptr<float> dev_ptr(dev_MAD);
thrust::device_ptr<float> min_pos = thrust::min_element(dev_ptr, dev_ptr + n*m);
int abs_pos = min_pos - dev_ptr;
float min_val=min_pos[0];
cudaMemcpy(&min_val, dev_MAD+abs_pos, sizeof(float), cudaMemcpyDeviceToHost);
// Print out the result
printf("Min=%.2f pos=%d\n",min_val,abs_pos);
Но эту программу распечатку: Min = -207521258711807190000000000000000000000,00 позы = 0
I Мы рассмотрели множество примеров сокращения, но, похоже, у каждого они имеют значения, хранящиеся в массиве, а не в каждом отдельном потоке.
Так на вопросы:
- Можно ли сделать функцию atomicMin вернуть расположение?
- Может ли кто-нибудь дать мне подсказку о том, как решить проблему с помощью библиотеки тяги?
Вы правильно поняли :) Я хотел бы реализовать первый способ, который вы упомянули. Насколько я понимаю, нужно сначала объявить вектор, используя thrust :: device_vector dev_MAD (n * m), а затем применить его к необработанному указателю float * dev_ptr = thrust :: raw_pointer_cast (dev_MAD.data()); Но как я индексирую вектор. Я попытался использовать стандартную нотацию dev_MAD [idx * n + idy], но, похоже, не заполняет массив всеми значениями –
user2594166
Ничего. Получил это работа :) Большое спасибо! – user2594166