OpenCL 双精度与 CPU 双精度不同

2024-02-15

我正在 Linux 中使用 GeForce GT 610 卡进行 OpenCL 编程。我的CPU和GPU双精度结果不一致。我可以在这里发布部分代码,但我首先想知道是否有其他人遇到过这个问题。当我运行多次迭代的循环时,GPU 和 CPU 双精度结果之间的差异变得很明显。该代码确实没有什么特别的,但如果有人感兴趣,我可以将其发布在这里。多谢。这是我的代码。请原谅 __ 和错误的格式,因为我是新来的:) 如您所见,我有两个循环,我的 CPU 代码本质上几乎是相同的版本。

#ifdef cl_khr_fp64
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#elif defined(cl_amd_fp64)
#pragma OPENCL EXTENSION cl_amd_fp64 : enable
#else
#error "Double precision floating point not supported by OpenCL implementation."

#endif

__kernel void simpar(__global double* fp, __global double* fp1,
  __global double* fp3, __global double* fp5,
 __global double* fp6, __global double* fp7,
 __global double* fp8, __global double* fp8Plus,
 __global double* x, __global double* v, __global double* acc,
 __global double* keBuf, __global double* peBuf,
 unsigned int prntstps, unsigned int nprntstps, double dt
 ) {
unsigned int m,i,j,k,l,t;
unsigned int chainlngth=100;
double dxi, twodxi, dxipl1, dximn1, fac, fac1, fac2, fac13, fac23;
double ke,pe,tke,tpe,te,dx;
double hdt, hdt2;
double alpha=0.16;
double beta=0.7;
double cmass;
double peTemp;
nprntstps=1001;
dt=0.01;
prntstps=100;
double alphaby4=beta/4.0;
hdt=0.5*dt;
hdt2=dt*0.5*dt;
double Xlocal,Vlocal,Acclocal;
unsigned int global_id=get_global_id(0);
if (global_id<chainlngth){
Xlocal=x[global_id];
Vlocal=v[global_id];
Acclocal=acc[global_id];
for (m=0;m<nprntstps;m++){

for(l=0;l<prntstps;l++){
               Xlocal =Xlocal+dt *Vlocal+hdt2*Acclocal; 
               x[global_id]=Xlocal;
               barrier(CLK_LOCAL_MEM_FENCE);

              Vlocal =Vlocal+ hdt * Acclocal; 
              barrier(CLK_LOCAL_MEM_FENCE);

            j = global_id - 1;
            k = global_id + 1;
            if (j == -1) {
                    dximn1 = 0.0;
            } else {
                    dximn1 = x[j];
            }
            if (k == chainlngth) {
                    dxipl1 = 0.0;
            } else {
                    dxipl1 = x[k];
            }
            dxi = Xlocal;
            twodxi = 2.0 * dxi;
            fac = dxipl1 + dximn1 - twodxi;
            fac1 = dxipl1 - dxi;
            fac2 = dxi - dximn1;
            fac13 = fac1 * fac1 * fac1;
            fac23 = fac2 * fac2 * fac2;
            Acclocal = alpha * fac + beta * (fac13 - fac23);

            barrier(CLK_GLOBAL_MEM_FENCE);

            Vlocal += hdt * Acclocal;
            v[global_id]=Vlocal;
            acc[global_id]=Acclocal;
            barrier(CLK_GLOBAL_MEM_FENCE);
       }
            barrier(CLK_GLOBAL_MEM_FENCE);

            tke = tpe = te = dx = 0.0;
            ke=0.5*Vlocal*Vlocal;//Vlocal*Vlocal;
           barrier(CLK_GLOBAL_MEM_FENCE);
            fp6[(m*100)+global_id]=ke;
            keBuf[global_id]=ke;
            ke=0.0; 
            barrier(CLK_GLOBAL_MEM_FENCE);


            j = global_id - 1;
            k = global_id + 1;
            if (j == -1) {
                    dximn1 = 0.0;
            } else {
                    dximn1 = x[j];
            }
            if (k == chainlngth) {
                    dxipl1 = 0.0;
            } else {
                    dxipl1 = x[k];
            }
            dxi = Xlocal;
            twodxi = 2.0 * dxi;
            fac = dxipl1 + dximn1 - twodxi;
            fac1 = dxipl1 - dxi;
            fac2 = dxi - dximn1;
            fac13 = fac1 * fac1 * fac1;
            fac23 = fac2 * fac2 * fac2;
            Acclocal = alpha * fac + beta * (fac13 - fac23);

            barrier(CLK_GLOBAL_MEM_FENCE);

            Vlocal += hdt * Acclocal;
            v[global_id]=Vlocal;
            acc[global_id]=Acclocal;
            barrier(CLK_GLOBAL_MEM_FENCE);
       }
            barrier(CLK_GLOBAL_MEM_FENCE);

            tke = tpe = te = dx = 0.0;
            ke=0.5*Vlocal*Vlocal;//Vlocal*Vlocal;
           barrier(CLK_GLOBAL_MEM_FENCE);
            fp6[(m*100)+global_id]=ke;
            keBuf[global_id]=ke;
            ke=0.0; 
            barrier(CLK_GLOBAL_MEM_FENCE);
            j = global_id - 1;
            k = global_id + 1;
            if (j == -1) {
                    dximn1 = 0.0;
            } else {
                    dximn1 = x[j];
            }
            if (k == chainlngth) {
                    dxipl1 = 0.0;
            } else {
                    dxipl1 = x[k];
            }
            dxi = Xlocal;
            twodxi = 2.0 * dxi;
            fac = dxipl1 + dximn1 - twodxi;
            fac1 = dxipl1 - dxi;
            fac2 = dxi - dximn1;
            fac13 = fac1 * fac1 * fac1;
            fac23 = fac2 * fac2 * fac2;
            Acclocal = alpha * fac + beta * (fac13 - fac23);

            barrier(CLK_GLOBAL_MEM_FENCE);

            Vlocal += hdt * Acclocal;
            v[global_id]=Vlocal;
            acc[global_id]=Acclocal;
            barrier(CLK_GLOBAL_MEM_FENCE);
       }
            barrier(CLK_GLOBAL_MEM_FENCE);

            tke = tpe = te = dx = 0.0;
            ke=0.5*Vlocal*Vlocal;//Vlocal*Vlocal;
           barrier(CLK_GLOBAL_MEM_FENCE);
            fp6[(m*100)+global_id]=ke;
            keBuf[global_id]=ke;
            ke=0.0; 
            barrier(CLK_GLOBAL_MEM_FENCE);
     if (global_id ==0){
             for(t=0;t<100;t++)
                  tke+=keBuf[t];
            }

            barrier(CLK_GLOBAL_MEM_FENCE); 
            k = global_id-1;
            if (k == -1) {
                dx = Xlocal;
            }else{
              dx = Xlocal-x[k];
            }

              fac = dx * dx;
              peTemp = alpha * 0.5 * fac + alphaby4 * fac * fac;
              fp8[global_id*m]=peTemp;
              if (global_id == 0)
                    tpe+=peTemp;

              barrier(CLK_GLOBAL_MEM_FENCE);  
              cmass=0.0;  
              dx = -x[100-1];
              fac = dx*dx;

              pe=alpha*0.5*fac+alphaby4*fac*fac;
              if (global_id==0){
              fp8Plus[m]=pe;
              tpe+=peBuf[0];
              fp5[m*2]=i;
              fp5[m*2+1]=cmass;
              te=tke+tpe;
              fp[m*2]=m;
              fp[m*2+1]=te;

             }
   barrier(CLK_GLOBAL_MEM_FENCE);
              //cmass /=100;
             fp1[(m*chainlngth)+global_id]=Xlocal-cmass; 
             // barrier(CLK_GLOBAL_MEM_FENCE);
              fp3[(m*chainlngth)+global_id]=Vlocal;
             // barrier(CLK_GLOBAL_MEM_FENCE);
             fp7[(m*chainlngth)+global_id]=Acclocal;

              barrier(CLK_GLOBAL_MEM_FENCE);
  }
 }

}


实际上,这在某种程度上是预期的行为。

在较旧的 x86 CPU 上,浮点数的长度为 80 位(Intel 的“长双” http://en.wikipedia.org/wiki/Long_double),并且仅在需要时截断为 64 位。 当浮点运算的 SIMD 单元/指令到达 x86 CPU 时,浮点双精度默认变为 64 位;但是,80 位仍然是可能的,具体取决于您的编译器设置。关于这一点,有很多值得阅读的内容:维基百科:浮点 http://en.wikipedia.org/wiki/Floating_point.

检查 OpenCL 的编译器设置and浮点“魔术”上的主机代码,以获得更好的结果一致性。计算absolute http://mathworld.wolfram.com/AbsoluteError.html and 相对误差 http://mathworld.wolfram.com/RelativeError.html您的值并检查此误差范围对于您的应用程序是否安全。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCL 双精度与 CPU 双精度不同 的相关文章

  • 确定 OpenCL 工作组大小的限制因素?

    我正在尝试在资源较少的嵌入式 GPU 上运行一些为桌面显卡编写的 OpenCL 内核 特别是 桌面版本假设始终支持至少 256 个工作组大小 但基于 Mali T628 ARM 的 GPU 仅保证 64 工作组大小 事实上 一些内核报告CL
  • 性能:boost.compute vs. opencl C++ 包装器

    以下代码分别使用 boost compute 和 opencl C 包装器将两个向量相加 结果显示 boost compute 几乎比 opencl c 包装器慢 20 倍 我想知道我是否错过了使用 boost compute 或者它确实很
  • OpenCL 中的矩阵求逆

    我正在尝试使用 OpenCL 加速一些计算 算法的一部分包括反转矩阵 是否有任何开源库或免费可用的代码来计算用 OpenCL 或 CUDA 编写的矩阵的 lu 分解 lapack dgetrf 和 dgetri 或一般求逆 该矩阵是实数且为
  • 内存复制速度对比 CPU<->GPU

    我现在正在学习 boost compute openCL 包装库 我的复制过程非常慢 如果我们将 CPU 到 CPU 的复制速度调整为 1 那么 GPU 到 CPU GPU 到 GPU CPU 到 GPU 复制的速度有多快 我不需要精确的数
  • 使用 GPU PyOpenCL 优化 python 代码的不同方法:内核 GPU/PyOpenCL 内的 extern 函数

    我使用以下命令来分析我的 Python 代码 python2 7 m cProfile o X2 non flat multiprocessing dummy prof X2 non flat py 然后 我可以全局可视化不同贪婪函数的重新
  • OpenGL-OpenCL 互操作传输时间 + 位图纹理

    两部分问题 我正在开展一个学校项目 使用生命游戏作为实验 gpgpu 的工具 我使用 OpenCL 和 OpenGL 进行实时可视化 目标是让这个东西尽可能大 更快 经过分析 我发现帧时间主要由 CL 获取和释放 GL 缓冲区决定 并且时间
  • 有关 OpenCL 内核编程的教程或书籍? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我认为这个问题足够具体 只是为了说清楚 我不是在寻找参考 而是在寻找教程 我对内核编程方面特别感兴趣 市
  • 如何在 OpenCL 中验证波前/扭曲大小?

    我使用的是 AMD Radeon HD 7700 GPU 我想使用以下内核来验证波前尺寸是否为 64 kernel void kernel test warpsize global T dataSet uint size size t id
  • 高清处理器显卡 (HD4000) 无法作为英特尔 OpenCL SDK 中的设备加载

    我使用 i7 3770K Ivy Bridge 和 HD 4000 并且我已经安装了最新的驱动程序和最新的OpenCL SDK http software intel com en us articles vcsource tools op
  • 在 OpenCL 内核中动态创建本地数组

    我有一个 OpenCL 内核 需要将一个数组作为多个数组进行处理 其中每个子数组总和都保存在本地缓存数组中 例如 想象一下捕鸟数组 1 2 3 4 10 30 1 23 每个工作组都有一个数组 在示例中我们有 2 个工作组 每个工作项处理两
  • opencl支持布尔变量吗?

    openCL 支持布尔变量吗 我目前正在使用 JOCL java 编写我的 openCL 调用代码 但我没有看到任何有关布尔值的信息 tl dr 是的 但是你应该在内核函数签名中避免它 是的 但a的大小bool is not定义的 因此 它
  • 如何在 Docker 容器内运行 OpenCL + OpenGL?

    目的是在 Docker 容器内运行 OpenCL OpenGL 互操作 应用程序 但我还没有成功 Intro 我有配备 NVidia 显卡的笔记本电脑 因此我认为利用 NVidia Dockerfiles 1 2 将是一个很好的起点 以下
  • 有一个不错的 OpenCL 入门套件吗? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我有一些经验OpenGL它是可编程管道 我愿意给OpenCL不过 尝试一下 有人可以提出一个很好的集成套件来使用OpenCL 我只知道石英作曲家看起来
  • 空的 openCL 程序抛出弃用警告

    我下载了 AMD APP 3 0 SDK 一旦包含 include
  • 如何在 Windows 上的 nvidia GPU 的 Visual Studio 2010 中配置 OpenCL?

    我在华硕笔记本电脑上的 Wwindows 7 操作系统上使用 NVIDIA GeForce GTX 480 GPU 我已经为 CUDA 4 2 配置了 Visual Studio 2010 如何在 Visual Studio 2010 上为
  • 在内核 OpenCL 中实现 FIFO 的最佳方法

    目标 在 OpenCL 中实现下图所示 OpenCl 内核所需的主要内容是将系数数组和临时数组相乘 然后最后将所有这些值累加为 1 这可能是最耗时的操作 并行性在这里非常有帮助 我正在为内核使用一个辅助函数来执行乘法和加法 我希望这个函数也
  • Linux 上的 OpenCL 编译

    我是 OpenCL 的新手 从昨天开始 我尝试使用 OpenCL 进行并行编程 而不是使用我更熟悉且以前体验过的 CUDA 现在我有 NVIDIA GTX 580 GPU Ubuntu Linux 12 04 操作系统和 CUDA SDK
  • 是否可以在 OpenCL 中并行运行求和计算?

    我是 OpenCL 的新手 不过 我了解 C C 基础知识和 OOP 我的问题如下 是否可以以某种方式并行运行求和计算任务 理论上可能吗 下面我将描述我尝试做的事情 任务例如是 double values new double 1000 l
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • OpenCL 内核在 Nvidia GPU 上每个线程使用多少寄存器?

    我的第一个问题是如何获取 Nvidia GPU 上 OpenCL 内核代码的寄存器使用信息 因为 nvcc 编译器给出了相同的使用信息nvcc ptxas options vCUDA 内核代码的标志 我还从 AMD GPU for Open

随机推荐