cuda的分支预测相当影响性能,怎么才能优化和提高代码效率呢?

kikopz 2009-12-29 04:13:24
if (tsflag)
{
bbg++;
bgo++;
if (err>=3)
ge3++;
err = 0;
}
else
{
err++;
if (bbg==2)
c2s++;
else
{
if (bbg>2)
c2p+=bbg-1;
}
bbg = 0;
}

在测试过程中,上面这段代码会将kernel的性能降低30%...

这种代码优化有什么思路吗?
...全文
681 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
taseaa 2010-04-27
  • 打赏
  • 举报
回复
GPU在条件控制能力方面非常弱,若程序使用条件控制语句会极大影响GPU程序的执行效率。当然,有部分条件控制语句可以用计算来代替,例如,判断两个整数是否相等可以用两个整数异或后再映射成0和1来代替。
+++++++++++++++++++++++++++++++++
请教一下,这个有没有示例代码看?
OpenGPU2010 2010-04-27
  • 打赏
  • 举报
回复
Cyrosly 2010-04-27
  • 打赏
  • 举报
回复
这么久的一个帖子还被挖出来,无语了,难道是群寂寞了,讨论来讨论区也没有看到个什么结果,哎
PepperYoung 2010-04-27
  • 打赏
  • 举报
回复
sum = (tid > 0) * 3 + (tid < 5) * 2;

对应的ptx,完全没有跳转,应该效率不错(btw,这段O3优化后的代码,还有有点小强的Orz)
cvt.s32.u16 %r1, %tid.x;
mov.s32 %r2, 0;
setp.gt.s32 %p1, %r1, %r2;
mov.s32 %r3, 5;
mov.s32 %r4, 2;
selp.s32 %r5, %r3, %r4, %p1;
mov.s32 %r6, 3;
mov.s32 %r7, 0;
selp.s32 %r8, %r6, %r7, %p1;
mov.s32 %r9, 4;
setp.le.s32 %p2, %r1, %r9;
selp.s32 %r10, %r5, %r8, %p2;

setp,大家应该了解吧。摘抄一下ptx文档中的selp:
selp d, a, b, c
d = (c == 1) ? a : b;
OpenGPU2010 2010-04-22
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 zuojuntao1 的回复:]

引用 3 楼 l7331014 的回复:
引用 2 楼 gogdizzy 的回复:
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:
C/C++ codeif( a==0 ) b=1;elseif( a==1 ) b=5;
转化成
b= (a<<2)+1;


还可以是b=(a==0?1:5);该也不慢,呵呵.

所见略同,惊天查看min的时候想……
[/Quote]

是的!

---------------------------------------------------------------------

开源图形处理器体系结构论坛(OpenGPU论坛)
http://www.opengpu.org/bbs/

OpenGPU Graphics Open Source community图形开源社区),聚焦领域(focus domain)包括:
* GPU Architecture图形处理器体系结构).
* Graphics Algorithm图形算法).
* Open Source Rendering Engine开源渲染器).
* Open Source GPU Simulator/RTL Implement开源GPU模拟器).
* GPGPU Programming 面向通用的图形处理器编程
* GPU General-purposed ComputingGPU通用计算).
.
zuojuntao1 2010-04-21
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 l7331014 的回复:]
引用 2 楼 gogdizzy 的回复:
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:
C/C++ codeif( a==0 ) b=1;elseif( a==1 ) b=5;
转化成
b= (a<<2)+1;


还可以是b=(a==0?1:5);该也不慢,呵呵.
[/Quote]
所见略同,惊天查看min的时候想到了一些判断语句可以采用这类方式来实现,min的执行为每周期八个操作
OpenGPU2010 2010-03-08
  • 打赏
  • 举报
回复
学习了~~~~~


---------------------------------------------------------------------

开源图形处理器体系结构论坛(OpenGPU论坛) http://www.opengpu.org/bbs/

OpenGPU Graphics Open Source community( 图形开源社区),聚焦领域(focus domain)包括:
* GPU Architecture(图形处理器体系结构)
* Graphics Algorithm(图形算法)
* GPGPU Programming (面向通用的图形处理器编程)
* Open Source Rendering Engine(开源渲染器)
* Open Source GPU Simulator/RTL Implement(开源GPU模拟器)
OpenGPU2010 2010-03-08
  • 打赏
  • 举报
回复
Branch degradation is a killer~~~~~~~~~~~~~


---------------------------------------------------------------------

开源图形处理器体系结构论坛(OpenGPU论坛) http://www.opengpu.org/bbs/

OpenGPU Graphics Open Source community( 图形开源社区),聚焦领域(focus domain)包括:
* GPU Architecture(图形处理器体系结构)
* Graphics Algorithm(图形算法)
* GPGPU Programming (面向通用的图形处理器编程)
* Open Source Rendering Engine(开源渲染器)
* Open Source GPU Simulator/RTL Implement(开源GPU模拟器)
  • 打赏
  • 举报
回复
首先向你道歉,在没有试验的情况下就做出了那个结论。后经过试验,得出了以下结论:

1>我的方法的时间是稳定的,即它只随数据规模而改变,而用if的方法会随着数据的分布有所差异,给出以下测试代码:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <intrin.h>
#pragma intrinsic(__rdtsc)

#define N 10000000
int a[N];
int b[N];
int c[N];

int main()
{
srand( time(NULL) );

int i;
for( i = 0; i < N; i++ ){
a[i] = rand();
//b[i] = (i &1) ? a[i] : -a[i]; // 如果b数组用这个方式初始化,那么时间就比较大
b[i] = rand();
}

unsigned __int64 t1, t2, t;

t1 = __rdtsc();
//for( i = 0; i < N; i++ ){ c[i] += !( a[i] - b[i] ); }
for( i = 0; i < N; i++ ){ if(a[i]==b[i] ) c[i]++; }
t2 = __rdtsc();
t = t2 - t1;

printf("%llu\n", t );

return 0;
}
引用 12 楼 taseaa 的回复:
if(a[2]==b[3]){c[4]++;}
转化成:
c[4] += !(a[2] - b[3]);


刚刚在CPU端和GPU端分别测试一下,
这种方式是不对的,
转换后的时间量:
在CPU端是原来的3倍多
CPU端快接近4倍。



2> CPU的预测已经非常好了,而if代码是1次比较和1次运算,而我的代码需要3次运算,所以速度慢。
taseaa 2010-03-07
  • 打赏
  • 举报
回复
引用 11 楼 gogdizzy 的回复:
其实我对ptx研究不深,所以仅提供我自己的一点看法。一般在cpu上是适用的。

引用 10 楼 taseaa 的回复:
请教一下:
类似
if(a[2]==b[3]){c[4]++;}
怎么转化?

c[4] += !(a[2] - b[3]);



引用 10 楼 taseaa 的回复:
还有那个“b=5”,这个五到哪去了?

你没仔细看前提条件,在a==1时,b=(a < <2) + 1就是5.

if(a[2]==b[3]){c[4]++;}
转化成:
c[4] += !(a[2] - b[3]);


刚刚在CPU端和GPU端分别测试一下,
这种方式是不对的,
转换后的时间量:
在CPU端是原来的3倍多
CPU端快接近4倍。

  • 打赏
  • 举报
回复
其实我对ptx研究不深,所以仅提供我自己的一点看法。一般在cpu上是适用的。

引用 10 楼 taseaa 的回复:
请教一下:
类似
if(a[2]==b[3]){c[4]++;}
怎么转化?


c[4] += !(a[2] - b[3]);

引用 10 楼 taseaa 的回复:
还有那个“b=5”,这个五到哪去了?


你没仔细看前提条件,在a==1时,b=(a<<2) + 1就是5.
taseaa 2010-03-05
  • 打赏
  • 举报
回复
引用 2 楼 gogdizzy 的回复:
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:
C/C++ codeif( a==0 ) b=1;elseif( a==1 ) b=5;
转化成
b= (a<<2)+1;

请教一下:
类似
if(a[2]==b[3]){c[4]++;}

怎么转化?
还有那个“b=5”,这个五到哪去了?
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 ilyyyfn 的回复:]
7楼的兄弟确定?
[/Quote]

自己看下ptx手册不就知道了?sdk的doc中有ptx手册的.
ilyyyfn 2010-01-24
  • 打赏
  • 举报
回复
7楼的兄弟确定?
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 gogdizzy 的回复:]
引用 3 楼 l7331014 的回复:
引用 2 楼 gogdizzy 的回复:
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:
C/C++ codeif( a==0 ) b=1;elseif( a==1 ) b=5;
转化成
b= (a < <2)+1;


还可以是b=(a==0?1:5);该也不慢,呵呵.


really?
据我所知,三目符只是为了书写简练,其实汇编代码和if没有区别的。
[/Quote]

看看ptx手册吧.呵呵.好像只要set一条ptx指令.
Cyrosly 2009-12-29
  • 打赏
  • 举报
回复


if(tsflag)
{
++bbg;
++bgo;
ge3+=(err>=3);
err=0;
} else {
++err;
const unsigned int cc=bbg==2;
c2s+=cc;
c2p+=__umul24(__umul24(1u^cc,bbg>2),bbg-1);
bbg=0;
}

OpenHero 2009-12-29
  • 打赏
  • 举报
回复
可以换成算法,最主要的是精简
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 l7331014 的回复:]
引用 2 楼 gogdizzy 的回复:
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:
C/C++ codeif( a==0 ) b=1;elseif( a==1 ) b=5;
转化成
b= (a < <2)+1;


还可以是b=(a==0?1:5);该也不慢,呵呵.
[/Quote]

really?
据我所知,三目符只是为了书写简练,其实汇编代码和if没有区别的。
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 gogdizzy 的回复:]
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:
C/C++ codeif( a==0 ) b=1;elseif( a==1 ) b=5;
转化成
b= (a<<2)+1;
[/Quote]

还可以是b=(a==0?1:5);该也不慢,呵呵.
  • 打赏
  • 举报
回复
一般都是通过查找表来去掉某些分支。或者尽量将某些分支转化成计算。

例如:

if( a== 0 ) b = 1;
else if( a == 1 ) b = 5;
转化成
b = (a<<2) + 1;
加载更多回复(1)

579

社区成员

发帖
与我相关
我的任务
社区描述
CUDA™是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题。 它包含了CUDA指令集架构(ISA)以及GPU内部的并行计算引擎。
社区管理员
  • CUDA编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧