2016-12-15 4 views
1

Я реализовал тот же алгоритм на процессоре с использованием C++ и на графическом процессоре с использованием CUDA. В этом алгоритме мне приходится решать интеграл численно, так как на него нет аналитического ответа. Функция, которую я должен интегрировать, - это странный многочлен кривой, а в конце есть функция exp.Cuda math vs C++ math

В C++

for(int l = 0; l < 200; l++) 
{ 
    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step; 
    r_int = r_int + step; 
} 

В CUDA

for(int l = 0; l < 200; l++) 
{ 
    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*__expf(-a6*r_int)*step; 
    r_int = r_int + step; 
} 

Выход:

Процессор: dose_output = 0,00165546

ГПУ: dose_output = 0,00142779

Я думаю, что функция math.h и функции __expf CUDA не вычисляют одно и то же. Я попытался удалить флаг компилятора -use_fast_math, думая, что это причина, но похоже, что обе реализации расходятся примерно на 20%.

Я использую CUDA для ускорения алгоритмов медицинской физики, и эти различия не очень хороши, так как я должен проследить, что один из выходов «более правдоподобен», чем другой, и это может быть катастрофическим для пациентов ,

Отличие от самой функции? В противном случае, я думаю, что это может произойти из memcopy факторов a_i или того, как я их получаю.

Edit: "Complete" Код

float a0 = 5.9991e-04; 
float a1 = -1.4694e-02; 
float a2 = 1.1588; 
float a3 = 4.5675e-01; 
float a4 = -3.8617e-03; 
float a5 = 3.2066e-03; 
float a6 = 4.7050e-01; 

float integral = 0.0; 

float r_int = 5.0; 
float step = 0.1/200; 

for(int l = 0; l < 200; l++) 
{ 
    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step; 
    r_int = r_int + step; 
} 

cout << "Integral=" << integral << endl; 

Я хотел бы предложить продолжить эту часть как на видеочипа и процессора. Значения от Carleton's seed database

+0

Комментарии не для расширенного обсуждения; этот разговор был [перемещен в чат] (http://chat.stackoverflow.com/rooms/130831/discussion-on-question-by-feynstein-cuda-math-vs-c-math). –

ответ

3

Вы используете менее точную реализацию exp() из API CUDA.

В принципе, вы можете использовать три версию ехра() на устройстве:

  • ехра(), тем более точный один
  • ехр(), который является одинарной точностью «эквивалента»
  • __expf(), которая является внутренней версией предыдущего, и тем менее точный

Вы можете прочитать больше о различных реализациях математических функций, в том числе с двойной точностью, подшипниковой PRECISIO n и искробезопасные версии, в документе Mathematical Functions Appendix документации CUDA:

D.2. Внутренние функции

Функции этого раздела могут использоваться только в коде устройства.

Среди этих функций являются менее точными, но более быстрыми версиями некоторые из функций стандартных функций .Оните имеет такое же имя с префиксом __ (например, __sinf (х)).Они быстрее, так как они отображают меньше инструкций.

На этой же странице вы прочтете, что параметр компилятора, который вы удалили, предотвращает замену любой функции на ее внутреннюю версию. Как вы явно использовать внутреннюю версию ехра(), убрав этот флаг не имеете никаких изменений для вас:

компилятора имеет возможность (-use_fast_math), который заставляет каждую функцию в таблице 8, чтобы компилировать его собственный аналог ,