Я хочу написать программу с использованием Thrust, которая должна вычислять локальные минимумы данных функций, f.i. sin(x)
. Я сделал это, аппроксимируя производную функции конечными разностями, а затем искал те абсциссы, где производная меняет знак. Теперь я хочу собрать местные минимумы. Я отметил локальные минимумы с «1» , а остальные точки с «0». Я сделал inclusive_scan
(для расчета мест на новой вкладке). Моя проблема заключается в сборе локальных минимумов с gather_if
(условие трафарета, минимумы карты), , но код не компилируется, и я не знаю почему.Поиск локальных минимумов выборочной функции CUDA Thrust
Может кто-нибудь объяснить, почему?
/**
* Copyright 1993-2012 NVIDIA Corporation. All rights reserved.
*
* Please refer to the NVIDIA end user license agreement (EULA) associated
* with this source code for terms and conditions that govern your use of
* this software. Any use, reproduction, disclosure, or distribution of
* this software and related documentation outside the terms of the EULA
* is strictly prohibited.
*/
#include <stdio.h>
#include <thrust/device_vector.h>
#include <thrust/gather.h>
#include <thrust/host_vector.h>
#include <thrust/reduce.h>
#include <thrust/copy.h>
#include <thrust/remove.h>
#include <thrust/functional.h>
#include <thrust/iterator/constant_iterator.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/scan.h>
#include <sys/time.h>
__host__ __device__ unsigned int bitreverse(unsigned int number) {
number = ((0xf0f0f0f0 & number) >> 4) | ((0x0f0f0f0f & number) << 4);
number = ((0xcccccccc & number) >> 2) | ((0x33333333 & number) << 2);
number = ((0xaaaaaaaa & number) >> 1) | ((0x55555555 & number) << 1);
return number;
}
struct is_even
{
__host__ __device__
bool operator()(const int x) {
return (x % 2) == 0;
}
};
struct select_mine
{
__host__ __device__
float operator()(const float x) {
return (x < 0) ? 1.0f : 0.0f;
}
};
struct bitreverse_functor
{
__host__ __device__ unsigned int operator()(const unsigned int &x) {
return bitreverse(x);
}
};
struct sign
{
__host__ __device__ float operator()(const float x) {
if (x > 0.0f)
return 1.0f;
if (x < 0.0f)
return -1.0f;
return 0.0f;
}
};
struct sine: public thrust::unary_function<float, float>
{
__host__ __device__
float operator()(float x) {
return sinf(x);
}
};
struct absolute: public thrust::unary_function<float, float>
{
__host__ __device__
float operator()(float x) {
if (x < 0.0f)
x = -x;
return x;
}
};
struct lokalne_minimum : public thrust::binary_function<float,float,float>
{
__host__ __device__
float operator()(float x, float y)
{
if (x > 0 && y < 0)
return 1.0f;
return 0.0f;
}
};
struct conv : public thrust::unary_function<float,int>
{
__host__ __device__
int operator()(float x)
{
return (int)(x);
}
};
using namespace thrust;
void help(char *arg) {
fprintf(stderr,
"Nieprawidlowe uzycie: %s [x1] [x2] [n]\nx1 - zakres od\nx2 - zakres do\nn - liczba podzialow zakresu\n",
arg);
}
int main(int argc, char **argv) {
if (argc != 4) {
help(argv[0]);
return 1;
}
int n = atoi(argv[3]);
float x1 = (float) atof(argv[1]);
float x2 = (float) atof(argv[2]);
if (n < 0 || x2 < x1) {
help(argv[0]);
return 1;
}
float step = (x2 - x1)/n;
fprintf(stderr, "Step: %f\n", step);
thrust::device_vector<float> oxdata(n);
thrust::device_vector<float> oydata(n);
thrust::device_vector<float> diff(n);
thrust::host_vector<float> ixdata(n);
// FIXME change it
for (int i = 0; i < n; i++)
ixdata[i] = x1 + i * step;
thrust::copy(ixdata.begin(), ixdata.end(), oxdata.begin());
thrust::transform(oxdata.begin(),oxdata.end(),oydata.begin(),sine());
thrust::transform(oydata.begin() + 1, oydata.end(), oydata.begin(),
diff.begin()+1, thrust::minus<float>());
thrust::copy(diff.begin(), diff.end(), ixdata.begin());
for (int i = 0; i < n; i++)
printf ("%f, ", ixdata[i]);
printf ("\n");
thrust::transform(diff.begin()+1,diff.end(), diff.begin(),diff.begin(),lokalne_minimum());
for (int i = 0; i < n; i++)
printf ("%f, ", ixdata[i]);
printf ("\n");
thrust::copy(oydata.begin(), oydata.end(), ixdata.begin());
for (int i = 0; i < n; i++)
printf ("%f, ", ixdata[i]);
printf ("\n");
thrust::copy(diff.begin(), diff.end(), ixdata.begin());
for (int i = 0; i < n; i++)
printf ("%f, ", ixdata[i]);
printf ("\n");
//thrust::inclusive_scan(diff.begin(),diff.end(),diff.begin());
thrust::copy(diff.begin(), diff.end(), ixdata.begin());
for (int i = 0; i < n; i++)
printf ("%f, ", ixdata[i]);
printf ("\n");
thrust::device_vector<int> minima(n);
thrust::device_vector<int> stencil(n);
thrust::host_vector<int> hminima(n);
thrust::transform(diff.begin(),diff.end(),minima.begin(),conv());
thrust::copy(minima.begin(),minima.end(),hminima.begin());
thrust::copy(minima.begin(),minima.end(),stencil.begin());
for (int i = 0; i < n; i++)
printf ("%d, ", hminima[i]);
printf ("\n");
thrust::inclusive_scan(minima.begin(), minima.end(),minima.begin());
thrust::copy(minima.begin(),minima.end(),hminima.begin());
for (int i = 0; i < n; i++)
printf ("%d, ", hminima[i]);
printf ("\n");
//thrust::gather_if(minima.begin(),minima.end(),stencil.begin(),ixdata.begin(),ixdata.begin());
return 0;
}
Это не компилируется, потому что вы смешиваете векторов устройств ('minima',' stencil'), и векторы-хозяева ('ixdata') в параметрах, передаваемых в' gather_if'. Вы должны передать либо все векторы устройств, либо все хост-векторы. Кроме того, я думаю, вы обнаружите, что 'gather_if' не делает то, что вы хотите, и вместо этого вы можете посмотреть [copy_if] (http://docs.thrust.googlecode.com/hg/group__stream__compaction.html#ga36d9d6ed8e17b442c1fd8dc40bd515d5) , Я пытался переделать свой код ко всему, что имело смысл для меня, но я решил, что не понимаю, что вы хотите показать в выходном векторе. –
Да, copy_if помог (+ трафарет для условия). Gather_if не нужен. Спасибо за ответ – tpsa