【CUDA 基础】3.5 展开循环
title: 【CUDA 基础】3.5 展开循环
categories:
- CUDA
- Freshman
tags:
- 展开归约
- 归约
- 模板函数
toc: true
date: 2018-04-19 21:02:08
Abstract: 本文介绍循环展开技术,在归约的基础上继续加速。
Keywords: 展开归约,归约,模板函数
开篇废话
博客从CSDN那边截流了一些流量,现在网站访问突然增多到让我有点不适应,于是,想想还是别总盯着流量看吧,注意文章质量,同时保证一定的更新,从数学到算法,最后到实现,优化,这些都做好,估计访问量会更多了。
到时候我就可以挂广告了,然后挣了钱吃煎饼就可以加个鸡蛋了!去网吧也能叫饮料了。。想想还有点小激动,感觉自己都有点膨胀了。
今天我们来做循环展开,GPU喜欢确定的东西,像前面讲解执行模型和线程束的时候,明确的指出,GPU没有分支预测能力,所有每一个分支他都是执行的,所以在内核里尽量别写分支,分支包括啥,包括if当然还有for之类的循环语句。
如果你不知道到为啥for算分支语句我给你写个简单到不能运行的例子:
for (itn i=0;i<tid;i++)
{
// to do something
}
如果上面这段代码出现在内核中,就会有分支,因为一个线程束第一个线程和最后一个线程tid相差32(如果线程束大小是32的话) 那么每个线程执行的时候,for终止时完成的计算量都不同,这就有人要等待,这也就产生了分支。
循环展开是一个尝试通过减少分支出现的频率和循环维护指令来优化循环的技术。
上面这句属于书上的官方说法,我们来看看例子,不止并行算法可以展开,传统串行代码展开后效率也能一定程度的提高,因为省去了判断和分支预测失败所带来的迟滞。
先来个c++ 入门循环
for (int i=0;i<100;i++)
{
a[i]=b[i]+c[i];
}
这个是最传统的写法,这个写法在各种c++教材上都能看到,不做解释,如果我们进行循环展开呢?
for (int i=0;i<100;i+=4)
{
a[i+0]=b[i+0]+c[i+0];
a[i+1]=b[i+1]+c[i+1];
a[i+2]=b[i+2]+c[i+2];
a[i+3]=b[i+3]+c[i+3];
}
没错,是不是很简单,修改循环体的内容,把本来循环自己搞定的东西,我们自己列出来了,这样做的好处,从串行较多来看是减少了条件判断的次数。
但是如果你把这段代码拿到机器上跑,其实看不出来啥效果,因为现代编译器把上述两个不同的写法,编译成了类似的机器语言,也就是,我们这不循环展开,编译器也会帮我们做。
不过值得注意的是:目前CUDA的编译器还不能帮我们做这种优化,人为的展开核函数内的循环,能够非常大的提升内核性能
在CUDA中展开循环的目的还是那两个:
- 减少指令消耗
- 增加更多的独立调度指令
来提高性能
如果这种指令
a[i+0]=b[i+0]+c[i+0];
a[i+1]=b[i+1]+c[i+1];
a[i+2]=b[i+2]+c[i+2];
a[i+3]=b[i+3]+c[i+3];
被添加到CUDA流水线上,是非常受欢迎的,因为其能最大限度的提高指令和内存带宽。
下面我们就在前面归约的例子上继续挖掘性能,看看是否能得到更高的效率。
展开的归约
完整内容参考[https://face2ai.com/CUDA-F-3-5-展开循环/])(https://face2ai.com/CUDA-F-3-5-展开循环/)
【CUDA 基础】3.5 展开循环的更多相关文章
- 【CUDA 基础】6.1 流和事件概述
title: [CUDA 基础]6.1 流和事件概述 categories: - CUDA - Freshman tags: - 流 - 事件 toc: true date: 2018-06-10 2 ...
- 【CUDA 基础】5.3 减少全局内存访问
title: [CUDA 基础]5.3 减少全局内存访问 categories: - CUDA - Freshman tags: - 共享内存 - 归约 toc: true date: 2018-06 ...
- 【CUDA 基础】5.1 CUDA共享内存概述
title: [CUDA 基础]5.1 CUDA共享内存概述 categories: - CUDA - Freshman tags: - CUDA共享内存模型 - CUDA共享内存分配 - CUDA共 ...
- 【CUDA 基础】6.2 并发内核执行
title: [CUDA 基础]6.2 并发内核执行 categories: - CUDA - Freshman tags: - 流 - 事件 - 深度优先 - 广度优先 - 硬件工作队列 - 默认流 ...
- 【CUDA 基础】5.2 共享内存的数据布局
title: [CUDA 基础]5.2 共享内存的数据布局 categories: - CUDA - Freshman tags: - 行主序 - 列主序 toc: true date: 2018-0 ...
- 【CUDA 基础】3.6 动态并行
title: [CUDA 基础]3.6 动态并行 categories: - CUDA - Freshman tags: - 动态并行 - 嵌套执行 - 隐式同步 toc: true date: 20 ...
- 【CUDA 基础】3.4 避免分支分化
- title: [CUDA 基础]3.4 避免分支分化 categories: - CUDA - Freshman tags: - 规约问题 - 分支分化 toc: true date: 2018- ...
- 【CUDA 基础】2.3 组织并行线程
title: [CUDA 基础]2.3 组织并行线程 categories: CUDA Freshman tags: Thread Block Grid toc: true date: 2018-03 ...
- CUDA基础介绍
一.GPU简介 1985年8月20日ATi公司成立,同年10月ATi使用ASIC技术开发出了第一款图形芯片和图形卡,1992年4月ATi发布了Mach32图形卡集成了图形加速功能,1998年4月ATi ...
随机推荐
- 怎样在 Vue 的 component 组件中使用 props ?
1. 在注册一个组件时, 添加一个 props 属性, 将需要添加的 props 作为数组的元素进行添加, 比如下面的例子中, 我们添加了一个变量 name , 他就是一个 props, 我们可以通过 ...
- 怎样在 Linux 上查看某个端口的相关信息?
比如 TCP端口 / UDP端口 / 端口占用程序的进程号 等, 这些信息都可以使用: netstat -atunlp | grep 端口号 来进行获取. 比如我们想获取 22 端口的相关信息: 这里 ...
- 二叉查找树 平衡二叉查找树 红黑树 b树 b+树 链表 跳表 链表
https://www.cnblogs.com/mojxtang/p/10122587.html二叉树的新增遍历查找
- Typora入门:全网最全教程
目录 简介 Markdown介绍 常用快捷键 块元素 换行符 标题级别 引用文字 无序列表 有序列表 任务列表 代码块 数学表达式 插入表格 脚注 分割线 目录(TOC) 跨度元素 链接 网址 图片 ...
- 使用 “Unicode 字符集 ” 使用错误,应该使用 “使用多字节字符集”
“void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)”: 不能将参数 1 从“const char ...
- location(重定向,跳转到其他网页)
<?php header('Location : https://www.baidu.com'); 这里是在响应头中添加一个 location 的头信息 客户端浏览器在接收到这个头信息过后会自动 ...
- 实现代码重启android app.
var Form1: TForm1; implementation uses System.DateUtils, Androidapi.JNI.GraphicsContentViewText, FMX ...
- Linux 链接脚本分析
作者:答疑助手lizuobin 原文: https://blog.csdn.net/lizuobin2/article/details/51779064 在前面学习的过程中,看代码时遇到 arch_i ...
- Nginx返回大长度的JSON数据被截断
1 添加Nginx参数,增加缓存字符串大小 head{ proxy_buffers 16 512k; //此处值代表nginx 设置 16个 512k 的块进行缓存,总共大小为16*512k prox ...
- SQL语句复习【专题一】
SQL语句复习[专题一] --创建用户 scott 并设置密码为 tiger create user scott identified by tiger --用户刚刚创建没有任何的权限,连登录的权限都 ...