У меня есть следующий (компилируемый и исполняемый) код с использованием CUDA Thrust для выполнения сокращений float2
массивов. Он работает правильноCUDA Уменьшение тяги с помощью массивов double2
using namespace std;
// includes, system
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <conio.h>
#include <typeinfo>
#include <iostream>
// includes CUDA
#include <cuda.h>
#include <cuda_runtime.h>
// includes Thrust
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
// float2 + struct
struct add_float2 {
__device__ float2 operator()(const float2& a, const float2& b) const {
float2 r;
r.x = a.x + b.x;
r.y = a.y + b.y;
return r;
}
};
// double2 + struct
struct add_double2 {
__device__ double2 operator()(const double2& a, const double2& b) const {
double2 r;
r.x = a.x + b.x;
r.y = a.y + b.y;
return r;
}
};
void main(int argc, char** argv)
{
int N = 20;
// --- Host
float2* ha; ha = (float2*) malloc(N*sizeof(float2));
for (unsigned i=0; i<N; ++i) {
ha[i].x = 1;
ha[i].y = 2;
}
// --- Device
float2* da; cudaMalloc((void**)&da,N*sizeof(float2));
cudaMemcpy(da,ha,N*sizeof(float2),cudaMemcpyHostToDevice);
thrust::device_ptr<float2> dev_ptr_1(da);
thrust::device_ptr<float2> dev_ptr_2(da+N);
float2 init; init.x = init.y = 0.0f;
float2 sum = thrust::reduce(dev_ptr_1,dev_ptr_2,init,add_float2());
cout << " Real part = " << sum.x << "; Imaginary part = " << sum.y << endl;
getch();
}
Однако, когда я изменяю float2
к double2
в программе main
, а именно
void main(int argc, char** argv)
{
int N = 20;
// --- Host
double2* ha; ha = (double2*) malloc(N*sizeof(double2));
for (unsigned i=0; i<N; ++i) {
ha[i].x = 1;
ha[i].y = 2;
}
// --- Device
double2* da; cudaMalloc((void**)&da,N*sizeof(double2));
cudaMemcpy(da,ha,N*sizeof(double2),cudaMemcpyHostToDevice);
thrust::device_ptr<double2> dev_ptr_1(da);
thrust::device_ptr<double2> dev_ptr_2(da+N);
double2 init; init.x = init.y = 0.0;
double2 sum = thrust::reduce(dev_ptr_1,dev_ptr_2,init,add_double2());
cout << " Real part = " << sum.x << "; Imaginary part = " << sum.y << endl;
getch();
}
я получаю exception
на reduce
линии. Как я могу использовать сокращение CUDA Thrust с помощью массивов double2
? Я делаю что-то неправильно? Заранее спасибо.
рабочего раствор следующего ответа TALONMIES»
с использованием патезраса;
// includes, system
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <conio.h>
#include <typeinfo>
#include <iostream>
// includes CUDA
#include <cuda.h>
#include <cuda_runtime.h>
// includes Thrust
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/reduce.h>
struct my_double2 {
double x, y;
};
// double2 + struct
struct add_my_double2 {
__device__ my_double2 operator()(const my_double2& a, const my_double2& b) const {
my_double2 r;
r.x = a.x + b.x;
r.y = a.y + b.y;
return r;
}
};
void main(int argc, char** argv)
{
int N = 20;
// --- Host
my_double2* ha; ha = (my_double2*) malloc(N*sizeof(my_double2));
for (unsigned i=0; i<N; ++i) {
ha[i].x = 1;
ha[i].y = 2;
}
// --- Device
my_double2* da; cudaMalloc((void**)&da,N*sizeof(my_double2));
cudaMemcpy(da,ha,N*sizeof(my_double2),cudaMemcpyHostToDevice);
thrust::device_ptr<my_double2> dev_ptr_1(da);
thrust::device_ptr<my_double2> dev_ptr_2(da+N);
my_double2 init; init.x = init.y = 0.0;
cout << "here3\n";
my_double2 sum = thrust::reduce(dev_ptr_1,dev_ptr_2,init,add_my_double2());
cout << " Real part = " << sum.x << "; Imaginary part = " << sum.y << endl;
getch();
}
Большое спасибо за ваш ответ. В чем причина такой несовместимости? Включает ли он также последние версии MSVC? На цитируемой веб-странице предлагается определить настраиваемую версию 'double2' как' struct'. Как насчет производительности? В прошлом я немного поиграл с собственной версией 'double2' в виде пары« двойных »чисел, но я понял, что решение с классом-оболочкой, использующим' double2', вместо пары 'double', было Быстрее. – JackOLantern
Я не знаком с компиляторами и библиотеками Microsoft, поэтому я не могу сказать вам больше, чем то, что я предложил в ответ. Что касается 'double2' по сравнению с struct - я так понимаю, вы не знаете, что' double2' * является * простой структурой (смотрите в 'vector_types.h'). Должно быть (и по моему опыту нет) какая-либо разница в испускаемом коде или производительности при использовании типа вектора CUDA и использования вашей собственной функционально эквивалентной структуры. – talonmies
Спасибо, я принял ваш ответ. Да, я знаю, что 'double2' является' struct', но перед определением есть специальные ключевые слова: '__device_builtin__ __builtin_align __ (16)'. До тех пор, как я знаю, они должны допускать совместный доступ к памяти. Это обеспечит некоторые улучшения по сравнению с настраиваемым определением, не использующим выравнивание? – JackOLantern