从校园输出值



我正在尝试使用校园库(CUDA多个精度算术库)。我已经下载了代码,并将其包含在我的项目中。由于它支持CPU和GPU,因此我从CPU开始,以了解其工作原理,并确保它可以完成我的需求。但目的是将其与Cuda一起使用。

我能够实例化实例并分配一个值,但是我不知道如何恢复物品。考虑:

#include <time.h>
#include "c:\vss\CAMPARY\Doubles\src_cpu\multi_prec.h"
int main()
{
    const char *value = "123456789012345678901234567";
    multi_prec<2> a(value);
    a.prettyPrint();
    a.prettyPrintBin();
    a.prettyPrintBin_UnevalSum();
    char *cc = a.prettyPrintBF();
    printf("n%sn", cc);
    free(cc);
}

编译,链接,运行(vs 2017)。但是输出是无助的:

Prec = 2
   Data[0] = 1.234568e+26
   Data[1] = 7.486371e+08
Prec = 2
   Data[0] = 0x1.987bf7c563caap+86;
   Data[1] = 0x1.64fa5c3800000p+29;
0x1.987bf7c563caap+86 + 0x1.64fa5c3800000p+29;
1.234568e+26 7.486371e+08

打印这样的双打可能很容易做到,但是它并没有太多告诉您要存储的128号码的值。如果无法输出结果,则执行高度精确的计算是有限的。

除了打印价值外,最终我还需要将这些数字转换为INT(如果有一种打印的方法,我愿意在浮标中尝试所有,但我担心准确性和速度会受到影响)。与Mpir(不支持CUDA)不同,校园没有任何相关的多精确INT类型,而只有漂浮。我可能可以将我需要的东西拼凑在一起(主要是添加/减去/比较),但是前提是我可以将校园价值的整数部分恢复出来,而我看不到这一点。

校园似乎没有任何文档,因此可以想象这些功能就在那里,我只是忽略了它们。我宁愿在校园讨论论坛/邮件列表中询问,但似乎没有一个。这就是为什么我在这里问。

总结:

  1. 有什么方法可以从校园输出128位(multi_prec<2>)值?
  2. 有什么方法可以从校园多_PREC中提取整数部分?也许我不理解的库中(许多)数学功能之一计算了?

实际上只有2个可能的答案:

  1. 有另一个在CUDA上有效的(更好的)多精确库,可以实现您需要的工作。
  2. 这是修改此库的方法以完成您需要的工作。

唯一可以给出第一个答案的人是CUDA程序员。不幸的是,如果有这样的图书馆,我会感到自信会知道并提到它。

至于#2,如果不是CUDA程序员,为什么有人会更新此库?还有其他更好的多次库库。唯一的好处是校园支持CUDA。这意味着唯一具有与图书馆合作或修改的真正动机的人是CUDA程序员。

,作为解决此问题最既得利益的CUDA程序员,我确实找出了一个解决方案(尽管是一个丑陋的解决方案)。我在这里发布它,希望这些信息对未来的校园程序员有价值。该库的信息不多,所以这是一个开始。


您需要了解的第一件事是校园如何存储其数据。而且,虽然并不复杂,但这并不是我所期望的。来自麦普尔

但是,不,校园的发展方式不同。查看代码,我们看到:

private:
    double data[prec];

现在,我以为这只是保留所需位数的任意方式。但是不,他们确实确实使用了prec双打。喜欢:

multi_prec<8> a("2633716138033644471646729489243748530829179225072491799768019505671233074369063908765111461703117249");
    // Looking at a in the VS debugger:
    [0] 2.6337161380336443e+99  const double
    [1] 1.8496577979210756e+83  const double
    [2] 1.2618399223120249e+67  const double
    [3] -3.5978270144026257e+48 const double
    [4] -1.1764513205926450e+32 const double
    [5] -2479038053160511.0 const double
    [6] 0.00000000000000000 const double
    [7] 0.00000000000000000 const double

因此,他们正在做的是将最大精度存储在第一个双人双重上,然后使用其余的来计算下一个双重,依此类推,依此最不重要的位)。请注意,其中一些是负的,这意味着前面值的总和比实际值大一些,它们正在向下校正。

考虑到这一点,我们回到了如何打印它的问题。

从理论上讲,您只需将所有这些添加在一起即可获得正确的答案。但是从定义上讲,我们已经知道C没有数据类型可以保持此大小的值。但是其他图书馆确实(例如Miper)。现在,Mpir在CUDA上不起作用,但不需要。您不想让您的CUDA代码打印出数据。无论如何,这都是您应该从主机那里做的事情。因此,使用CUDA的全部功能,cudamemcpy的计算也是如此,然后使用MPIR将其打印出来:

#define MPREC 8
void ShowP(const multi_prec<MPREC> value)
{
    multi_prec<MPREC> temp(value), temp2;
    // from mpir at mpir.org
    mpf_t mp, mp2;
    mpf_init2(mp, value.getPrec() * 64); // Make sure we reserve enough room
    mpf_init(mp2); // Only needs to hold one double.
    const double *ptr = value.getData();
    mpf_set_d(mp, ptr[0]);
    for (int x = 1; x < value.getPrec(); x++)
    {
        // MPIR doesn't have a mpf_add_d, so we need to load the value into
        // an mpf_t.
        mpf_set_d(mp2, ptr[x]);
        mpf_add(mp, mp, mp2);
    }
    // Using base 10, write the full precision (0) of mp, to stdout.
    mpf_out_str(stdout, 10, 0, mp); 
    mpf_clears(mp, mp2, NULL);
}

与上面的Multi_prec中存储的数字一起使用,这将输出完全相同的值。是的。

这不是一个特别优雅的解决方案。必须添加第二个库来打印第一个值,这显然是最佳的。而且这种转换也不是那么快。但是打印通常比计算频率少。如果您进行一个小时的计算价值和少量印刷品,则性能并不重要。而且它完全无法打印出来。

校园有很多缺点(不在意,不支持,未受欢迎)。但是对于在CUDA上需要MP号码的人(尤其是如果您需要SQRT),这是我找到的最好的选择。

相关内容

  • 没有找到相关文章

最新更新