分布式计算课程补充笔记 part 4
▶ 并行通讯方式:
map 映射 全局一到一 全局单元素计算操作
transpose 转置 一到一 单元素位移
gather 收集 多到一 元素搬运不计算
scatter 分散 一到多 元素搬运不计算
stencil 模板 全局多到一 模板计算(例如卷积)
reduce 归约 全局多到一 元素计算成一个值
scan/sort 扫描排序 全局多到多 元素局部或全局调整
▶ 几种扫描方法:
● 线性扫描,O(n) 个 step(完全不并行),O(n) 次加法。适用于只有一个处理器的情形
[ , , , , , , , ]
[ ] // 每个数和它左1格的数字相加
[ ]
...
[ ] // 结果
● 闭扫描的 Hillis Steele 算法,O(log n) 个 step(理解为该矩形的宽度),O(n log n) 次加法(理解为该矩形的面积)。适用于处理器较多,算法受步数限制的情形,步骤效率(step efficiency)较高,步数少
[ , , , , , , , ]
[ ] // 每个数和它左1格的数字相加,没有左1格的数字原样补齐
[ ] // 每个数和它左2格的数字相加,没有左2格的数字原样补齐
[ ] // 每个数和它左4格的数字相加,没有左4格的数字原样补齐
[ ] // 结果
● 开扫描的 Blelloch 算法,O(log n) 个 step(HS方法的两倍),O(n) 次加法(把 n 个数字加成一个)。适用于处理器较少,算法受工作量限制的情形,工作效率(work efficiency)较高,步数多
[ , , , , , , , ]
[ ] // 第2k个数和它左1格的数相加,第2k-1个数原样补齐
[ ] // 第4k个数和它左2格的数相加,其他数原样补齐
[ ] // 第8k个数和它左4格的数相加,其他数原样补齐(其实不需要)
[ ] // 写出中间的数(表示原数组前半段的和),最后一个数补0(表示原数组第一个数以前的和)
[ ] // 交叉计算,l'=r,r'=l+r
[ ] // 写出前后半段中间的数(表示前后半段各前半段的和)
[ ] // 交叉计算
[ ] // 写出各半段中间的数(表示各半段中前半段的和)
[ ] // 交叉计算,结果
▶ compact过程:
input: [ , , , ,,,,,,,,]
filter: [ , , , , , , , , , , , ] // 由筛选期计算得到,可以并行
address: [ , , , , , , , , , , , ] // filter 的开扫描,若 input[i] 被选中,则它应该放到 output 的第 address[i] 位置
output: [ , ,,,,,] // 将输入数组中的值依地址数组相应位置上的值进行输出:[output[address[i]]=input[i] if filter[i] for i in range(len(input))];
▶ APOD: analyze, parallelize, optimice, deploy。
● 并行优化的两种体现:
■ 弱缩放:当并行规模增大时,如何解决更大规模的问题
■ 强缩放:当并行规模增大时,如何缩短解决问题的时间
● CUDA 程序优化方法思路:
■ 优化GPU占用率:各 SM、各 block、各 thread 分配时间相近的任务
■ 合并内存访问,减少全局内存的访问
■ 优化同步延迟:减少 __syncthreads(); 的等待时间,尽量使内存带宽饱和。适量减少每个 block 的 thread 数量,增加每个 SM 的 block 数量来改善,但是若 block 过小、过于分散不利于合并全局内存访问,当线程块数量为流处理器数量的2倍时,计算效率最高(经验关系)
■ 最小化线程分支发散(改进算法)。重整 Warp,使得分支在 Warp 之间而不是 Warp 之内
■ 优化循环结构,减少循环次数差距
■ 使用cuda内置函数,有目的的使用单双精度数字
■ 管理线程通讯(适当增加或减少线程间通讯,调整计算效率)
▶ 7 种常见并行程序优化模式
1、数据布局变换(Data layout transformation)
struct foo { float a; float b; } aa[]; //结构数组,array of atructures, AOS struct foo { float a[]; float b[]; } aa; //数组结构,structure of arrays, SOA
2、发散 - 收集变换(Scatter - to - gather transformation)
out[i]=in[i-]+in[i]+in[i+] // 分散地址访问 out[i]=in[i-]+in[i]+in[i+] // 紧缩地址访问
3、瓦片(Tiling)利用更广高速度的内存形式,如 __shared__
4、私有化(Privatization)将多个线程需要同时用到的同一内存数据分割或另存为多个副本,供不同线程单独使用,避免内存读取冲突和延迟。例如计算直方图
5、进仓(Binning)将输出位置映射到输入数据的较小子集上。例如筛选距离某点最近的 n 个点,先画粗网格进行第一轮筛选,剩下的点都不要
6、压缩(Compaction)创造一个仅包含活动元素的紧凑数据组,防止多余的线程闲置。加速比例不能超过线程束中的线程数量,即 32 倍。例如大矩阵乘法分块
7、正则化(Regularization)负载均衡,设置每个线程需要完成的工作量的上限,超出的部分利用其它的核函数或者CPU来补充完成。例如典例:地图上寻找相邻的给定点
▶ Warp 含有 32 条 thread,优先按照 threadIdx.x 划分,再按照 threadIdx.y,最后按照 threadIdx.z 划分。同一时刻只能执行统一一条指令,分支结构会先执行一部分,挂起后再执行另一部分,总时间变长。
// 典例:
switch(threadIdx.x%){case ~ : foo<<<,>>>();} // 减速为1/32,每个线程分别执行一次 switch(threadIdx.x%){case ~ : foo<<<,>>>();} // 减速为1/32,因为每个Warp中只有32个线程,不可能有更改多的分支 switch(threadIdx.y){case ~ : foo<<<,dim3(,)>>>();} // 不减速,因为每个Warp中各线程的threadIdx.y是相等的 switch(threadIdx.y){case ~ : foo<<<,dim3(,)>>>();} // 减速为1/2,因为每个Warp中各线程threadIdx.y有两个值 switch(threadIdx.x%){case ~ : foo<<<,>>>();} // 减速为1/2,共 2 种取值 switch(threadIdx.x/){case ~ : foo<<<,>>>();} // 不减速,所有线程计算值相等 switch(threadIdx.x/){case ~ : foo<<<,>>>();} // 减速为1/4,共 4 种取值
▶ 利用宏__CUDA_ARCH__生成同时在主机和设备上运行的同一个程序,并具有不同处理方式,宏__CUDA_ARCH__是一个整数,百位表示计算功能集主版本号
__host__ __device__ int myFunc(void)
{
#if defined(__CUDA_ARCH__)
// Device code here
#else
// Host code here
#endif
}
▶ GPU工作调度机制:将流中工作映射,先按工作种类(核函数引擎、内存拷贝引擎等)分类再按时间先后串行,不同流的同一类型的工作之间仍然曾在阻塞,应该采用广度优先策略,分拆多个任务穿插道不同的流中,以便在一个流占用核函数引擎的时候另一个流占用内存拷贝引擎
● 若同时运行两个指向同一地址的流,则仍会并行运行,但结果未定义
cudaMemcpyAsync(&d_array,&h_array,ARRAY_BYTES,cudaMemcpyHostToDevice,s1);
foo<<<blocks,threads,s2>>>(d_array);
▶ 图 G = (V,E) 的并行广度优先遍历算法(O(n2)):
● 开启V个线程,将根节点标记为0,其他标记为-1
● 开启V个线程,每次循环检查相应的顶点是否存在这样一条边,该边的一端已经被标价,另一端没有被标记:若存在,则将没有被标记的端点标记为已标记的端点的值+1,并且报告遍历尚未结束;若不存在,则不做改变,报告该节点遍历已经结束
__global__ void bfs(const Edge * edges, Vertex * vertices, int currentDepth, bool *done)
{
int e = blockDim.x * blockIdx.x + threadIdx.x;
int dfirst = vertices[edges[e].first], dsecond = vertices[edge[e].second];
if (dfirst == currentDepth && dsecond == -)
{
vertices[vsecond] = dfirst + ;
*done = false;
}
else if (dsecond == current_depth && dfirst == -)
{
vertices[vfirst] = dsecond + ;
*done = false;
}
else
*done = true;
return;
}
▶ 图 G = (V,E) 的并行广度优先遍历算法(O(n)):
● 用类似SCR的方式存储一张图,保存两个数组
C:依次保存每个节点的邻居的编号,长度等于边的条数
R:依次保存每个节点的邻居在 C 中的起点位置,长度等于节点个数+1,最后一个位置存放边的条数,方便最后一个节点的计算
D:依次保存每个节点的深度,长度等于节点个数
● 步骤:
■ 对边界中的每个节点,利用R找到其邻居编号在 C 中的起点以及邻居个数,如对于编号为v的节点,其邻居编号在C中起点为 R[v],邻居个数为 R[v+1] - R[v]
■ 找到边界的所有相邻节点,依次入队
■ 删除队中已经被标记过的节点(根据D中数据),队空说明已经完成了遍历
■ 确认新节点,标记为边界,返回 1
▶ cuBLAS 使用范例(编译时添加 -L cublas)
{
int N = << ;
cublasInit();
cublasAlloc(N, sizeof(float), (void **)&d_x);
cublasAlloc(N, sizeof(float), (void **)&d_y); cublasSetVector(N,sizeof(x[]), x, , d_x, );
cublasSetVector(N,sizeof(y[]), y, , d_y, ); cublasSaxpy(N, 2.0, x,, y, ); // 单精度 y += a*x cublasSetVector(N,sizeof(y[]), d_y, , y, ); cublasFree(d_x);
cublasFree(d_y);
cublasShutdown();
}
▶ MCUDA 工具(Linux平台)将 CUDA 代码编译为可以在主机 CPU 上运行的程序
▶ Thrust库,CUDA中类似STL的并行函数库
▶ CudaDMA库,优化全局内存和共享内存交换
▶ Kahan求和算法:人为记录浮点数加法过程中每一步的舍入误差,并在计算最后进行补偿,减小了总体计算误差
{
float a[N], temp, compensation = 0.0f, sum_old, sum = 0.0f;
for(int i = ; i < N; i++)
{
sum_old = sum; //记录前i个数的和
temp = a[i] + compemsation; //计算补偿以后的新待加数
sum += temp; //获得前i+1个数的和
compensation = temp + sum_old - sum0; //计算新的补偿
}
sum += compensation; //剩余补偿
}
分布式计算课程补充笔记 part 4的更多相关文章
- 分布式计算课程补充笔记 part 2
▶ 并行计算八字原则:负载均衡,通信极小 ▶ 并行计算基本形式:主从并行.流水线并行.工作池并行.功能分解.区域分解.递归分治 ▶ MPI 主要理念:进程 (process):无共享存储:显式消息传递 ...
- 分布式计算课程补充笔记 part 1
▶ 高性能计算机发展历程 真空管电子计算机,向量机(Vector Machine),并行向量处理机(Parallel Vector Processors,PVP),分布式并行机(Parallel Pr ...
- 分布式计算课程补充笔记 part 3
▶ OpenMP 的任务并行 (task parallelism):显式定义一系列可执行的任务及其相互依赖关系,通过任务调度的方式多线程动态执行,支持任务的延迟执行 (deferred executi ...
- 分布式计算课程补充笔记 part 1.5
▶ 编写 SLURM 脚本 #!/bin/bash #SBATCH -J name # 任务名 #SBATCH -p gpu # 分区名,可为 cpu 或 gpu #SBATCH -N # 节点数 # ...
- (转载)林轩田机器学习基石课程学习笔记1 — The Learning Problem
(转载)林轩田机器学习基石课程学习笔记1 - The Learning Problem When Can Machine Learn? Why Can Machine Learn? How Can M ...
- 03、同事分享课程的笔记 —《Android应用低功耗设计》
这是安卓组的同事一个月前分享的一节课程,听课时写了一下笔记,之前是写在本子上的,感觉内容挺不错 的,就保存在博客了吧,方便回看. 他曾经在就职于英特尔公司,是与芯片设计相关的,这课程标题虽然是与安卓相 ...
- Coursera台大机器学习基础课程学习笔记1 -- 机器学习定义及PLA算法
最近在跟台大的这个课程,觉得不错,想把学习笔记发出来跟大家分享下,有错误希望大家指正. 一机器学习是什么? 感觉和 Tom M. Mitchell的定义几乎一致, A computer program ...
- 分布式计算框架学习笔记--hadoop工作原理
(hadoop安装方法:http://blog.csdn.net/wangjia55/article/details/53160679这里不再累述) hadoop是针对大数据设计的一个计算架构.如果你 ...
- [基础]斯坦福cs231n课程视频笔记(三) 训练神经网络
目录 training Neural Network Activation function sigmoid ReLU Preprocessing Batch Normalization 权重初始化 ...
随机推荐
- Android : 跟我学Binder --- (5) C++实现
目录: Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制? Android : 跟我学Binder --- (2) AIDL分析及手动实现 ...
- Kruskal算法(题目还是:畅通工程)
那还是先把题目丢出来,是HDU上的一道题 畅通工程 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- java 几种对象
POJO(plain old java object):普通的java对象,有别于特殊的java对象(含继承约束等)和EJB.POJO一般只有一系列的属性和相应的get.set方法. PO( ...
- 虚拟机U盘挂载
虚拟机中U盘挂载 一.连接U盘 虚拟机中 虚拟机→可移动设备→Syntek USB......(U盘的名称)→连接: 二.查看U盘的UUID “lsblk -f”: UUID为 35E6-9 ...
- IDEA 类图功能使用方法
1. Ctrl+Shift+Alt+U显示类图,(可以选中代码中类,再按快捷键,直接进入此类的类图) 2. 在类图中,选中某类右击显示Show Implementations,弹出子类的选择框. 按S ...
- LVS DR模式搭建、keepalived+lvs
1.LVS DR模式搭建 条件: 即三台机器,在同一内网. 编辑脚本文件:/usr/local/sbin/lvs_dr.sh #! /bin/bashecho 1 > /proc/sys/net ...
- UEFI+GPT双硬盘安装Win10+Ubuntu16.04双系统
转载请注明出处:http://www.cnblogs.com/willnote/p/6725594.html 安装环境 SSD+HDD双盘,Win10安装在SSD里,HDD分出来60G安装Ubuntu ...
- tmpfs临时文件系统,是一种基于内存的文件系统
在Linux系统内存中的虚拟磁盘映射,可以理解为使用物理内存当做磁盘,利用这种文件系统,可以有效提高在高并发场景下的磁盘读写,但是重启后数据会丢失. 1.查看tmpfs路径 (系统默认开启,大小约为物 ...
- 用turtle画图
turtle是python自带一个寓教于乐的小乌龟,可以控制乌龟移动(机器人),可以留下足迹. turtledemo里有许多官方例子.刚才随性而发做,看了介绍随手画了一个,有点像自动原包机,通过简单的 ...
- 什么是pytorch(2Autograd:自动求导)(翻译)
Autograd: 自动求导 pyTorch里神经网络能够训练就是靠autograd包.我们来看下这个包,然后我们使用它来训练我们的第一个神经网络. autograd 包提供了对张量的所有运算自动求导 ...