使C ++ Pi近似在GPU Nvidia 970M CUDA上的Paralell中运行

时间:2018-09-05 23:21:33

标签: c++ cuda gpu nvidia pi

我从Chudnovsky公式中获得了用于Pi逼近的代码,我想越来越快地做到这一点。但是我对如何处理GPU没有任何经验或想法。如何使此代码在GPU Nvidea 970M上运行?它在C ++上。有一些容易实现的库吗?使用我的处理器,它的运行时间约为3到4秒...

#include <iostream>
#include <windows>
#include <iomanip>
#include <cmath>

double fac(double num) {
    double result = 1.0;
    for (double i=2.0; i<num; i++)
       result *= i;
    return result;
}

int main() {
    using namespace std;
    double pi=0.0;
    for (double k = 0.0; k < 10.0; k++) {
        pi += (pow(-1.0,k) * fac(6.0 * k) * (13591409.0 + (545140134.0 * k)))
            / (fac(3.0 * k) * pow(fac(k), 3.0) * pow(640320.0, 3.0 * k + 3.0/2.0));
    }
    pi *= 12.0;
    cout << setprecision(100000000) << 1.0 / pi << endl;
system("Pause");    
return 0;
}

1 个答案:

答案 0 :(得分:1)

在委派具有多个内核的GPU之前,建议您首先使用一个内核优化算法。

运行阶乘值

对于每个k值,阶乘函数始终从2.0开始。计算如下:

+----+-------------------+  
| 1! | 1                 |   
+----+-------------------+  
| 2! | 1 * 2             |  
+----+-------------------+  
| 3! | 1 * 2 * 3         |  
+----+-------------------+  
| 5! | 1 * 2 * 3 * 4 * 5 |   
+----+-------------------+  

随着k的值变大,这些迭代的时间加起来。

阶乘可以迭代表示为:

+----+--------+   
| 1! | 1      |   
+----+--------+  
| 2! | 1! * 2 |  
+----+--------+  
| 3! | 2! * 3 |  
+----+--------+  
| 5! | 4! * 5 |   
+----+--------+  

换句话说,下一个阶乘使用先前的阶乘值并乘以k的值。

您的main看起来像:

    int main()
    {
      double k_factorial = 1.0;
      //...
      for (/* ... */)
      {
        if (k > 1.0) k_factorial *= k;
        //...
                / (fac(3.0 * k) * pow(k_factorial, 3.0) * pow(640320.0, 3.0 * k + 3.0/2.0));
    //...
  }

由于您有3个不同的阶乘:fac(3.0 * k), fac(k),fac(6.0 * k),因此可以使用3个不同的阶乘变量并在for循环内更新它们的值。

运行pow变量

类似于阶乘变量,您可以为pow函数获取运行值。
pow(-1.0, k)可以替换为:

double pow_sign = 1.0; // pow(-1.0, 0)
//...
for (//...
{
  pow_sign *= -1.0;
  pi += (pow_sign * //...

此外,我们知道pow(x, 3)x * x * x相同。进行替换:
pow(fac(k), 3.0)-> factorial_k * factorial_k * factorial_k

代数简化

您也可以代数简化您的赋值语句。 例如,制作一个包含以下各列的表:

+-----+--------------+--------------+  
|  k  | fac(6.0 * k) | fac(3.0 * k) |  
+-----+--------------+--------------+  
|  0  |              |              |  
+-----+--------------+--------------+  
|  1  |              |              |  
+-----+--------------+--------------+  

看看您是否注意到任何图案。
还要垂直重写分配,以查看是否可以通过分解简化。

开发GPU内核

将计算优化为运行或迭代方法后,就可以委托给多个内核。

第一步是弄清楚如何将工作划分为可以并行运行的部分。

将您的计算分为三部分并运行(在一个内核上)。验证正确性。

下一步是研究“ c ++并行编程”以获取有关如何在平台上使用并行处理运行程序的说明,或者在“ c ++使用gpu多核”上搜索Internet。

您希望每个核心所花费的工作量要比设置核心所花费的时间更多。