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 中的最佳本地/全局工作规模

    我想知道如何在 OpenCL 中为不同设备选择最佳的本地和全局工作大小 AMD NVIDIA INTEL GPU 有什么通用规则吗 我是否应该分析设备的物理构建 多处理器数量 多处理器中的流处理器数量等 这取决于算法 实现吗 因为我看到一些
  • 在 OpenCL 中,mem_fence() 与 Barrier() 相比有何作用?

    Unlike barrier 我想我明白 mem fence 不影响工作组中的所有项目 OpenCL 规范指出 第 6 11 10 节 对于mem fence 命令加载和存储执行内核的工作项 所以它适用于single工作项 但同时 在第 3
  • 性能:boost.compute vs. opencl C++ 包装器

    以下代码分别使用 boost compute 和 opencl C 包装器将两个向量相加 结果显示 boost compute 几乎比 opencl c 包装器慢 20 倍 我想知道我是否错过了使用 boost compute 或者它确实很
  • 并行化 std::nth_element 和 std::partition

    我正在移植使用的 C 代码std nth element and std partition到 OpenCL nth element http www cplusplus com reference algorithm nth elemen
  • 工作组之间的 OpenCL 同步

    是否可以同步 OpenCL 工作组 例如 我有 100 个工作组 每个工作组只有一个项目 不要问我为什么 这是一个例子 我需要对每个工作项设置障碍 以确保所有工作组都会在这 100 个工作组中的每个工作项达到此障碍点后继续 不 你不能 您可
  • 如何在 OpenCL 中验证波前/扭曲大小?

    我使用的是 AMD Radeon HD 7700 GPU 我想使用以下内核来验证波前尺寸是否为 64 kernel void kernel test warpsize global T dataSet uint size size t id
  • OpenCL 内核是异步执行的吗?

    对于 CUDA 我知道它们是在向默认流 空流 发出启动命令后异步执行的 那么在 OpenCL 中又如何呢 示例代码如下 cl context context cl device id device id cl int err cl kern
  • CMake找不到NVIDIA的opencl sdk

    我刚刚安装了 NVIDIA CUDA 工具套件 用它在 Windows 8 1 上开发 OpenCL 应用程序 我遇到了一些问题 1 FinedOpenCl cmake 不起作用 因为 Nvidia 工具包未设置 opencl dir cm
  • GPU 显存带宽理论与实际

    作为在 GPU 上运行的算法分析的一部分 我觉得我正在达到内存带宽的要求 我有几个复杂的内核执行一些复杂的操作 稀疏矩阵乘法 归约等 和一些非常简单的操作 当我计算每个内核读取 写入的总数据时 似乎所有 重要的 都达到了约 79GB s 的
  • GPGPU:普通 PC 陷入困境的后果

    我在一本书中读到 在波前或扭曲中 所有线程共享一个公共程序计数器 那么它的后果是什么呢 为什么这很重要 NVIDIA GPU 一次执行 32 个线程 扭曲 AMD GPU 一次执行 64 个线程 波前 控制逻辑 读取和数据路径的共享减少了面
  • 在 OpenCL 内核中动态创建本地数组

    我有一个 OpenCL 内核 需要将一个数组作为多个数组进行处理 其中每个子数组总和都保存在本地缓存数组中 例如 想象一下捕鸟数组 1 2 3 4 10 30 1 23 每个工作组都有一个数组 在示例中我们有 2 个工作组 每个工作项处理两
  • CUDA PTX 代码 %envreg<32> 特殊寄存器

    我尝试使用 CUDA 驱动程序 API 运行由 cl 内核生成的 PTX 汇编代码 我采取的步骤是这些 标准 opencl 程序 1 加载 cl内核 2 JIT编译 3 获取编译好的ptx代码并保存 到目前为止 一切都很好 我注意到 ptx
  • 多个 OpenCl 内核

    我只是想问 是否有人可以提醒我在相继使用几个简单内核时要注意什么 我可以用同样的吗CommandQueue 我可以跑几次吗clCreateProgramWithSource cl program与不同的cl program 我忘记了什么 T
  • OpenCL:为什么指向指针的指针不能作为参数传递给内核函数?

    你好 我只是想澄清一下为什么我们不能将 2D 数组指针作为参数传递给内核 为什么不允许 如果我使用它作为参数会发生什么 在内部 因为我知道代码会给出一些错误 请只做那些需要的 因为在 OpenCL 1 x 中设备有一个独立的地址空间 在设备
  • 使用 OpenCL 支持构建 OpenCV

    在 CMake 中 我使用 OpenCL Enable ON 构建了 OpenCV 它自动检测到OPENCL INCLUDE DIR路径但是OPENCL LIBRARY即使单击配置后也是空的 为了OPENCL LIBRARY我也没有看到浏览
  • 如何在 pyopencl 中创建可变大小的 __local 内存?

    在我的 C OpenCL 代码中我使用clSetKernelArg创建 可变尺寸 local我的内核中使用的内存 OpenCL 本身不提供该内存 看我的例子 clSetKernelArg clKernel ArgCounter sizeof
  • OpenCL 内核在 Nvidia GPU 上每个线程使用多少寄存器?

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

    我想用UMat所以我的代码可以使用 OpenCL OpenCV 3 0 0 Beta 在 GPU 和 CPU 上运行 但我找不到将图像文件读入的方法UMat或转换一个Mat to UMat 如何将图像读入UMat 样品用于Mat to UM
  • OpenCL 内核参数中的 Char***?

    我需要通过一个vector
  • nvidia GPU 上的内核真的有超时吗?

    寻找为什么我的内核产生奇怪的错误消息或仅 0 结果的答案我发现了这个answer https stackoverflow com questions 3988645 cl out of resources for 2 millions fl

随机推荐