#matlab #thrust
#matlab #thrust
Вопрос:
Привет, я хотел реализовать цикл, который имеет чрезвычайно большую тягу, но я нахожу его намного медленнее, чем обычный код на C . Не могли бы вы, пожалуйста, сказать мне, где я ошибаюсь. fi и fj являются основными векторами
xsize обычно составляет около 7-8-значного числа
thrust::host_vector <double> df((2*floor(r)*(floor(r) 1) 1)*n*n);
thrust::device_vector<double> gpu_df((2*floor(r)*(floor(r) 1) 1)*n*n);
for(i=0;i<xsize;i )
{
gpu_df[i]=(fi[i]-fj[i]);
if(gpu_df[i]<0)
gpu_df[i]=0;
else
gpu_df[i]=gpu_df[i]*(fi[i]-fj[i]);
if(gpu_df[i]>255)
gpu_df[i]=255;
// cout<<fi[i]<<"n";
}
df=gpu_df;
Я чувствую, что код не распараллеливается. Не могли бы вы, пожалуйста, помочь мне.
Ответ №1:
Чтобы запускать программы на графическом процессоре с помощью Thrust, вам нужно написать их в терминах алгоритмов Thrust, таких как reduce
, transform
, sort
и т.д. В этом случае мы можем записать вычисления в терминах transform
, поскольку цикл просто вычислял функцию F(fi[i], fj[i])
и сохранял результат в df[i]
. Обратите внимание, что мы должны сначала переместить входные массивы на устройство перед вызовом transform
, потому что Thrust требует, чтобы входные и выходные массивы находились в одном и том же месте.
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/functional.h>
#include <cstdio>
struct my_functor
: public thrust::binary_function<float,float,float>
{
__host__ __device__
float operator()(float fi, float fj)
{
float d = fi - fj;
if (d < 0)
d = 0;
else
d = d * d;
if (d > 255)
d = 255;
return d;
}
};
int main(void)
{
size_t N = 5;
// allocate storage on host
thrust::host_vector<float> cpu_fi(N);
thrust::host_vector<float> cpu_fj(N);
thrust::host_vector<float> cpu_df(N);
// initialze fi and fj arrays
cpu_fi[0] = 2.0; cpu_fj[0] = 0.0;
cpu_fi[1] = 0.0; cpu_fj[1] = 2.0;
cpu_fi[2] = 3.0; cpu_fj[2] = 1.0;
cpu_fi[3] = 4.0; cpu_fj[3] = 5.0;
cpu_fi[4] = 8.0; cpu_fj[4] = -8.0;
// copy fi and fj to device
thrust::device_vector<float> gpu_fi = cpu_fi;
thrust::device_vector<float> gpu_fj = cpu_fj;
// allocate storage for df
thrust::device_vector<float> gpu_df(N);
// perform transformation
thrust::transform(gpu_fi.begin(), gpu_fi.end(), // first input range
gpu_fj.begin(), // second input range
gpu_df.begin(), // output range
my_functor()); // functor to apply
// copy results back to host
thrust::copy(gpu_df.begin(), gpu_df.end(), cpu_df.begin());
// print results on host
for (size_t i = 0; i < N; i )
printf("f(%2.0lf,%2.0lf) = %3.0lfn", cpu_fi[i], cpu_fj[i], cpu_df[i]);
return 0;
}
Для справки, вот выходные данные программы:
f( 2, 0) = 4
f( 0, 2) = 0
f( 3, 1) = 4
f( 4, 5) = 0
f( 8,-8) = 255
Комментарии:
1. Спасибо, wnbell. Возможно ли это и для 2d-векторов. Я хочу что-то вроде xi [i] [0]-xj [i] [0] так будет ли это похоже на xi [0]-xj [0]?
2. Thrust предоставляет только одномерный векторный контейнер, поэтому вам придется решить, как сгладить 2d-вектор в вектор 1d. Предполагая, что вы выравниваете все 2d-векторы одинаково, вы часто можете игнорировать 2d-природу данных при вызове алгоритмов типа
transform
.