本节主要介绍NBody算法的OpenCL性能优化。

1、NBody

NBody系统主要用来通过粒子之间的物理作用力来模拟星系系统。每个粒子表示一个星星,多个粒子之间的相互作用,就呈现出星系的效果。

上图为一个粒子模拟星系的图片:Source: THE GALAXY-CLUSTER-SUPERCLUSTER CONNECTION,http://www.casca.ca/ecass/issues/1997-DS/West/west-bil.html

由于每个粒子之间都有相互作用的引力,所以这个算法的复杂度是N2的。下面我们主要探讨如何优化算法以及在OpenCL基础上优化算法。

2、NBody算法

假设两个粒子之间通过万有引力相互作用,则任意两个粒子之间的相互作用力F公式如下:

最笨的方法就是计算每个粒子和其它粒子的作用力之和,这个方法通常称作N-Pair的NBody模拟。

粒子之间的万有引力和它们之间的距离成反比,对于一个粒子而言(假设粒子质量都一样),远距离粒子的作用力有时候很小,甚至可以忽略。Barnes Hut 把3D空间按八叉树进行分割,只有在相邻cell的粒子才直接计算它们之间的引力,远距离cell中的粒子当作一个整体来计算引力。

3、OpenCL优化Nbody

在本节中,我们不考虑算法本身的优化,只是通过OpenCL机制来优化N-Pair的NBody模拟。

最简单的实施方法就是每个例子的作用力相加,代码如下:

for(i=0; i<n; i++){ ax = ay = az = 0;// Loop over all particles "j” for (j=0; j<n; j++) {

//Calculate Displacementdx=x[j]-x[i];dy=y[j]-y[i];dz=z[j]-z[i];

// small eps is delta added for dx,dy,dz = 0invr= 1.0/sqrt(dx*dx+dy*dy+dz*dz +eps);invr3 = invr*invr*invr;f=m[ j ]*invr3;

// Accumulate acceleration ax += f*dx; ay += f*dy;az += f*dx;}// Use ax, ay, az to update particle positions}

我们对每个粒子计算作用在它上面的合力,然后求在合力作用下,delta时间内粒子的新位置,并把这个新位置当作下次计算的输入参数。

没有优化的OpenCL kernel代码如下:

__kernel void nbody_sim_notile(__global float4* pos ,__global float4* vel,int numBodies,float deltaTime,float epsSqr,__local float4* localPos,__global float4* newPosition,__global float4* newVelocity)

{unsigned int tid = get_local_id(0);unsigned int gid = get_global_id(0);unsigned int localSize = get_local_size(0);

// position of this work-itemfloat4 myPos = pos[gid];float4 acc = (float4)(0.0f, 0.0f, 0.0f, 0.0f);

// load one tile into local memoryint idx = tid * localSize + tid;localPos[tid] = pos[idx];

// calculate acceleration effect due to each body// a[i->j] = m[j] * r[i->j] / (r^2 + epsSqr)^(3/2)for(int j = 0; j < numBodies; ++j){// Calculate acceleartion caused by particle j on particle ilocalPos[tid] = pos[j];float4 r = localPos[j] - myPos;float distSqr = r.x * r.x + r.y * r.y + r.z * r.z;float invDist = 1.0f / sqrt(distSqr + epsSqr);float invDistCube = invDist * invDist * invDist;float s = localPos[j].w * invDistCube;

// accumulate effect of all particlesacc += s * r;}

float4 oldVel = vel[gid];

// updated position and velocityfloat4 newPos = myPos + oldVel * deltaTime + acc * 0.5f * deltaTime * deltaTime;newPos.w = myPos.w;

float4 newVel = oldVel + acc * deltaTime;

// write to global memorynewPosition[gid] = newPos;newVelocity[gid] = newVel;}

在这种实现中,每次都要从global memory中读取其它粒子的位置,速度,内存访问= N reads*N threads= N2

我们可以通过local memory进行优化,一个粒子数据读进来以后,可以被p*p个线程共用,p*p即为workgroup的大小,对于每个粒子,我们通过迭代p*p的tile,累积得到最终结果。

优化后的kernel代码如下:

__kernel void nbody_sim(

__global float4* pos ,

__global float4* vel,

int numBodies,

float deltaTime,

float epsSqr,

__local float4* localPos,__global float4* newPosition,__global float4* newVelocity)

{unsigned int tid = get_local_id(0);

unsigned int gid = get_global_id(0);

unsigned int localSize = get_local_size(0);

// Number of tiles we need to iterate

unsigned int numTiles = numBodies / localSize;

// position of this work-item

float4 myPos = pos[gid];

float4 acc = (float4)(0.0f, 0.0f, 0.0f, 0.0f);

for(int i = 0; i < numTiles; ++i)

{

// load one tile into local memory

int idx = i * localSize + tid;

localPos[tid] = pos[idx];

// Synchronize to make sure data is available for processing

barrier(CLK_LOCAL_MEM_FENCE);

// calculate acceleration effect due to each body

// a[i->j] = m[j] * r[i->j] / (r^2 + epsSqr)^(3/2)

for(int j = 0; j < localSize; ++j)

{

// Calculate acceleartion caused by particle j on particle i

float4 r = localPos[j] - myPos;

float distSqr = r.x * r.x + r.y * r.y + r.z * r.z;

float invDist = 1.0f / sqrt(distSqr + epsSqr);

float invDistCube = invDist * invDist * invDist;

float s = localPos[j].w * invDistCube;

// accumulate effect of all particles

acc += s * r;

}

// Synchronize so that next tile can be loaded

barrier(CLK_LOCAL_MEM_FENCE);

}

float4 oldVel = vel[gid];

// updated position and velocity

float4 newPos = myPos + oldVel * deltaTime + acc * 0.5f * deltaTime * deltaTime;

newPos.w = myPos.w;

float4 newVel = oldVel + acc * deltaTime;

// write to global memory

newPosition[gid] = newPos;

newVelocity[gid] = newVel;}

下面是在AMD, NV两个平台上性能测试结果:

AMD GPU = 5870 Stream SDK 2.2

Nvidia GPU = GTX 480 with CUDA 3.1

另外,在程序中,也尝试了循环展开,通过展开内循环,从而减少GPU执行分支指令,我的测试中,使用展开四次,得到的FPS比没展开前快了30%。(AMD 5670显卡)。具体实现可以看kernel代码中的__kernel void nbody_sim_unroll函数。在AMD平台上,使用向量化也可以提高10%左右的性能。

最后提供2篇NBody优化的文章:

—Nvidia GPU Gems

—http://http.developer.nvidia.com/GPUGems3/gpugems3_ch31.html

—Brown Deer Technology

—http://www.browndeertechnology.com/docs/BDT_OpenCL_Tutorial_NBody.html

完整的代码可从:http://code.google.com/p/imagefilter-opencl/downloads/detail?name=amduniCourseCode7.zip&can=2&q=#makechanges 下载。

转载于:https://www.cnblogs.com/mikewolf2002/archive/2012/01/31/2333906.html

AMD OpenCL大学课程(12) 性能优化案例NBody相关推荐

  1. AMD OpenCL 大学课程

    AMD OpenCL大学课程是非常好的入门级OpenCL教程,通过看教程中的PPT,我们能够很快的了解OpenCL机制以及编程方法.下载地址:http://developer.amd.com/zone ...

  2. MySQL第12天:MySQL索引优化分析之性能优化案例实践

    MySQL索引优化分析之性能优化案例实践 执行计划中各select_type含义可以看:MySQL第11天:MySQL索引优化分析之性能分析 https://weibo01.blog.csdn.net ...

  3. Android 性能优化案例

    2019独角兽企业重金招聘Python工程师标准>>>         之前看到一篇关于优化Android性能的文章,写的很不错.但由于一直没有使用过,最近恰好优化Performan ...

  4. 【中亦安图】清算/报表/日终跑批程序之性能优化案例(5)

    第一章 技术人生系列 · 我和数据中心的故事(第五期)-清算/报表/日终跑批程序之性能优化案例(一) 中亦安图 | 2016-02-18 21:40 前言 不知不觉,技术人生系列·我和数据中心的故事来 ...

  5. 老李案例分享:Weblogic性能优化案例

    老李案例分享:Weblogic性能优化案例 POPTEST的测试技术交流qq群:450192312 网站应用首页大小在130K左右,在之前的测试过程中,其百用户并发的平均响应能力在6.5秒,性能优化后 ...

  6. Spark的性能优化案例分析(下)

    前言 Spark的性能优化案例分析(上),介绍了软件性能优化必须经过进行性能测试,并在了解软件架构和技术的基础上进行.今天,我们通过几个 Spark 性能优化的案例,看一看所讲的性能优化原则如何落地. ...

  7. AntDB 落地某省电信大数据中心项目的性能优化案例分享

    亚信科技AntDB 落地某省电信大数据中心项目的性能优化案例分享 某省电信大数据中心项目采购了一套亚信科技AntDB 3.1分布式数据库,2018年8月初开始建设,建设周期一个月.9月份投入运行后,至 ...

  8. 中国大学 MOOC Android 性能优化:冷启动优化总结

    联系我们: 有道技术团队助手:ydtech01 / 邮箱:ydtech@rd.netease.com 本文的重点在于如何定量的排查冷启动过程中的耗时操作,并提供对应的优化思路和实践方法总结.同时文本涉 ...

  9. Android性能优化案例研究(上)

    为什么80%的码农都做不了架构师?>>>    英文原文:Android Performance Case Study  编译:ImportNew - 孙立 译 者前言: 这是Goo ...

最新文章

  1. class.forname()中要写相对路径吗?_Deno 会对 Node 造成威胁吗?
  2. nginx https http2
  3. java mvc增删改查_springmvc-CRUC增删改查
  4. linux cpu核数和线程数,cpu个数、核数和线程的理解
  5. 李开复:2018中国最大AI红利?是政策
  6. Java 条形码 二维码 的生成与解析
  7. Flink 在快手实时多维分析场景的应用
  8. tp3.2框架运行原理
  9. MacOS 苹果 快捷键
  10. python中交集并集用什么符号表示_Python实现两个list求交集,并集,差集的方法示例...
  11. 通过纯CSS实现文字前添加图片
  12. JDBC之程序编写步骤
  13. 数据太多?3款免费数据分析软件,分分钟解决
  14. JAVA主线程Sleep以后,Eden不断增加
  15. 从软件管理后台看其匠心所在
  16. 3M年度调查显示,疫情挑战下中国受访者对科学的信任度居全球首位
  17. vlc option以及常见问题解决方案
  18. 计算机和电气工程研究生就业,56所“电气工程专业”实力很强的大学,毕业后就业率和收入都很高...
  19. java 腾讯认证_Java 腾讯验证码平台使用实例
  20. Lammps剪切作用的两种实现方法及对比—Deform以及Velocity

热门文章

  1. HTTP Status 404 -(tomcat,springmvc,ModelAndView)
  2. 使用新操作码在比特币现金上进行首次原子竞猜
  3. php开发app接口-封装类
  4. 二、2.4版本之前的apache的安装
  5. 在阿里云容器服务上创建一个使用Redis的Python应用
  6. 【9.4】socket模拟http请求
  7. python程序打包exe
  8. 使用Nginx做图片服务器时候,配置之后图片访问一直是 404问题解决
  9. 算法总结之 打印二叉树的边界节点
  10. 细说Activity与Task(任务栈)