▶ 协作组,要求 cuda ≥ 9.0,一个简单的例子见 http://www.cnblogs.com/cuancuancuanhao/p/7881093.html

● 灵活调节需要进行通讯的线程组合(不一定是线程块或是线程束)的尺寸,在更多粒度上进行线程协作。

● 协作组功能支持 CUDA 的各种并行模式,包括生产者 - 消费者并行(producer-consumer parallelism),机会并行(opportunistic parallelism),全网个同步(global synchronization)。

● 构成要素:① 参与协作的线程组合(即协作组整体)的数据类型;② 从 CUDA lauch API 中创建协作组(intrinsic groups?)的操作;③ 将现有协作组划分为新的协作组的操作;④ 协作组内的栅栏同步函数;⑤ 检查组内属性和执行组内特定命令的操作(如线程表决函数)。

● 块内协作组(Intra-block Group)使用方法。

 # include <cooperative_groups.h>        // 使用的头文件

 using namespace cooperative_groups;     // 命名空间

 thread_block g = this_thread_block();   // 将当前线程块打包为一个协作组,命名为 g

 thread_group gTile = tiled_partition(g, SIZE);
// 将之前的协作组分割成大小为 SIZE 的协作组(SIZE 可以取 1,2,4,8,16,32),但组内不能使用线程束表决函数和统筹函数 thread_block_tile<SIZE> gTile = tiled_partition<SIZE>(g);
// 同样的分割函数,使用模板函数,编译时处理,比函数 tiled_partition() 更高效,且组内可以使用线程束表决函数和统筹函数 // 协作组的一些方法
void sync(); // 协作组同步(协作组内的线程栅栏同步)
unsigned size(); // 获得协作组的大小(线程个数)
unsigned thread_rank(); // 获得当前线程在协作组内的编号
bool is_valid(); // 协作组是否有效(符合 API 约束)
dim3 group_index(); // 指出当前线程块在线程格中的编号
dim3 thread_index(); // 指出当前线程在线程块中的编号 // 协作组内也可以使用的表决函数和统筹函数(成员函数)
int shfl();
int shfl_down();
int shfl_up();
int shfl_xor();
int any();
int all();
int ballot();
int match_any();
int match_all();

● 线程束发生分支的时候设备将会串行执行每个分支,在同道中保持活跃的所有线程称为合并的,协作组有能力发现并为合并的线程创建一个组。

 coalesced_group active = coalesced_threads();// 在分支中,将当前活跃的线程创建为一个协作组

● 发现模式。两个示例代码段等价,但没看懂在干什么。

 {
unsigned int writemask = __activemask();
unsigned int total = __popc(writemask);
unsigned int prefix = __popc(writemask & __lanemask_lt());
// Find the lowest-numbered active lane
int elected_lane = __ffs(writemask) - ;
int base_offset = ;
if (prefix == )
base_offset = atomicAdd(p, total);
base_offset = __shfl_sync(writemask, base_offset, elected_lane);
int thread_offset = prefix + base_offset;
return thread_offset;
}
{
cg::coalesced_group g = cg::coalesced_threads();
int prev;
if (g.thread_rank() == )
prev = atomicAdd(p, g.size());
prev = g.thread_rank() + g.shfl(prev, );
return prev;
}

● 线程格同步,需要额外的一些步骤。

 // 通过 CUDA Driver API 的函数 cuDeviceGetAttribute() 来检查设备是否支持 cooperative launch 属性
int pi = ;
cuDevice dev;
cuDeviceGet(&dev, )
cuDeviceGetAttribute(&pi, CU_DEVICE_ATTRIBUTE_COOPERATIVE_LAUNCH, dev);// 如果支持,则 pi 被置 1 // 使用函数 cudaLaunchCooperativeKernel() 或 CUDA Driver API 中的几种调用方法来启动内核,不能使用 <<< >>>
cudaLaunchCooperativeKernel(const T *func, dim3 gridDim, dim3 blockDim, void **args, size_t sharedMem = , cudaStream_t stream = ); // 建议精心优化线程格尺寸和线程块尺寸(下面两例分别是使用最大线程块数和自动优化线程块数)
{
cudaDeviceProp deviceProp;
cudaGetDeviceProperties(&deviceProp, dev);
cudaLaunchCooperativeKernel((void*)my_kernel, deviceProp.multiProcessorCount, numThreads, args);
}
{
cudaOccupancyMaxActiveBlocksPerMultiprocessor(&numBlocksPerSm, my_kernel, numThreads, ));
cudaLaunchCooperativeKernel((void*)my_kernel, numBlocksPerSm, numThreads, args);
} // 使用函数 this_grid() 来获得当前线程格,以及使用线程格同步函数
grid_group grid = this_grid();
grid.sync(); // 编译命令,打开 Relocatable Device Code(允许分离编译)
nvcc - arch = sm_61 - rdc = true mytestfile.cu - o mytest

● 多设备同步,需要额外的一些步骤。

 // 通过 CUDA Driver API 的函数 cuDeviceGetAttribute() 来检查设备是否支持 cooperative multi-device launch 属性
int pi = ;
cuDevice dev;
cuDeviceGet(&dev, )
cuDeviceGetAttribute(&pi, CU_DEVICE_ATTRIBUTE_COOPERATIVE_MULTI_DEVICE_LAUNCH, dev);// 如果支持,则 pi 被置 1 // 使用结构 CUDA_LAUNCH_PARAMS_st 来存储需要调用的内核的相关参数
typedef struct CUDA_LAUNCH_PARAMS_st
{
CUfunction function;
unsigned int gridDimX;
unsigned int gridDimY;
unsigned int gridDimZ;
unsigned int blockDimX;
unsigned int blockDimY;
unsigned int blockDimZ;
unsigned int sharedMemBytes;
CUstream hStream;
void **kernelParams;
}
CUDA_LAUNCH_PARAMS; // 使用函数 cudaLaunchCooperativeKernelMultiDevice() 来启动内核,该函数允许主机线程创建一个跨设备的内核,以提供多设备同步功能
cudaLaunchCooperativeKernelMultiDevice(CUDA_LAUNCH_PARAMS *launchParamsList, unsigned int numDevices); // 使用函数 this_multi_grid() 来获得当前线程格,以及使用多设备同步函数
multi_grid_group multi_grid = this_multi_grid();
multi_grid.sync(); // 编译命令,与线程格同步相同

■ 其他要点:

① 该 API 保证了操作的原子性,保证各主机线程在所有指定设备上独立的启动内核;不能将两个 launchParamsList 映射到同一个设备上

② 使用的所有设备必须具有相同的计算能力 major 和 minor 号;所有设备上使用的线程格尺寸、线程块尺寸和共享内存大小必须相同;通过该 API 启动的函数应该是相同的,API 内并没有内置相关检查。

③ 内核中使用的所有 __device__,__constant__,__managed__ 变量在各设备中相互独立,应该在启动内存钱分别初始化完成。

CUDA C Programming Guide 在线教程学习笔记 Part 9的更多相关文章

  1. CUDA C Programming Guide 在线教程学习笔记 Part 5

    附录 A,CUDA计算设备 附录 B,C语言扩展 ▶ 函数的标识符 ● __device__,__global__ 和 __host__ ● 宏 __CUDA_ARCH__ 可用于区分代码的运行位置. ...

  2. CUDA C Programming Guide 在线教程学习笔记 Part 4

    ▶ 图形互操作性,OpenGL 与 Direct3D 相关.(没学过,等待填坑) ▶ 版本号与计算能力 ● 计算能力(Compute Capability)表征了硬件规格,CUDA版本号表征了驱动接口 ...

  3. CUDA C Programming Guide 在线教程学习笔记 Part 2

    ▶ 纹理内存使用 ● 纹理内存使用有两套 API,称为 Object API 和 Reference API .纹理对象(texture object)在运行时被 Object API 创建,同时指定 ...

  4. CUDA C Programming Guide 在线教程学习笔记 Part 10【坑】

    ▶ 动态并行. ● 动态并行直接从 GPU 上创建工作,可以减少主机和设备间数据传输,在设备线程中调整配置.有数据依赖的并行工作可以在内核运行时生成,并利用 GPU 的硬件调度和负载均衡.动态并行要求 ...

  5. CUDA C Programming Guide 在线教程学习笔记 Part 13

    ▶ 纹理内存访问补充(见纹理内存博客 http://www.cnblogs.com/cuancuancuanhao/p/7809713.html) ▶ 计算能力 ● 不同计算能力的硬件对计算特性的支持 ...

  6. CUDA C Programming Guide 在线教程学习笔记 Part 8

    ▶ 线程束表决函数(Warp Vote Functions) ● 用于同一线程束内各线程通信和计算规约指标. // device_functions.h,cc < 9.0 __DEVICE_FU ...

  7. CUDA C Programming Guide 在线教程学习笔记 Part 7

    ▶ 可缓存只读操作(Read-Only Data Cache Load Function),定义在 sm_32_intrinsics.hpp 中.从地址 adress 读取类型为 T 的函数返回,T ...

  8. CUDA C Programming Guide 在线教程学习笔记 Part 3

    ▶ 表面内存使用 ● 创建 cuda 数组时使用标志 cudaArraySurfaceLoadStore 来创建表面内存,可以用表面对象(surface object)或表面引用(surface re ...

  9. CUDA C Programming Guide 在线教程学习笔记 Part 1

    1. 简介 2. 编程模型 ▶ SM version 指的是硬件构架和特性,CUDA version 指的是软件平台版本. 3. 编程接口.参考 http://chenrudan.github.io/ ...

随机推荐

  1. js 如何控制文本域输入内容在一定间隔时间段才触发事件查询相关数据

    <script>var flag = 0;var t;function openFlag () { t = setTimeout(function(){flag = 1; dosometh ...

  2. C# NPOI导出Excel和EPPlus导出Excel

    转自:http://www.cnblogs.com/tanpeng/p/6155749.html 系统中经常会使用导出Excel的功能.之前使用的是NPOI,但是导出数据行数多就报内存溢出. 最近看到 ...

  3. Hibernate有五大核心接口,分别是:Session Transaction Query SessionFactoryConfiguration

    Session接口: Session接口 Session 接口对于Hibernate 开发人员来说是一个最重要的接口.然而在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都 ...

  4. DMABUFF

    1.DMABUF框架提供了在多设备间共享缓存的通用方法,支持DMABUF的设备驱动可以将一个DMA缓存以文件句柄的方式输出到用户空间(输出者规则),以文件句柄的方式从用户空间获取一个DMA缓存,这个文 ...

  5. 转 微软Sysinternals Suite工具13年12月版下载

    Sysinternals Suite 是微软出品的一套集成数十个绿色软件的系统工具包.Sysinternals Suite 和IT之家的魔方电脑大师设计一样,里面的各个小工具组件都可以单独拿出来运行, ...

  6. MSDN Windows XP Professional x64 Edition with SP2 +VL简体中文语言包+序列号

    [资源名称]---Windows XP Professional x64 Edition with SP2 - VL (English)[资源类型]---ISO镜像[资源语言]---英语+简体中文[杀 ...

  7. 前端可视化建模技术概览,包括:GoJS

    我推荐使用的: 库 网址 备注 GoJS https://gojs.net/latest/samples/flowchart.html 推荐使用 相关文章: 前端可视化建模技术概览:http://le ...

  8. jmeter ---模拟http请求/发送gzip数据

    jmeter中get请求gzip数据的方法: 在jmeter线程组中添加“http信息头管理器”,并添加名称:Accept-Encoding值: gzip,deflate注:HTTP信息头Accept ...

  9. ML(5):KNN算法

    K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,可以简单的理解为由那离自己最近的K个点来投票决定待分类数据归为哪一类.这个算法是机器学习里面一个比较经典的算法, ...

  10. 【python】网络编程-SocketServer 实现客户端与服务器间非阻塞通信

    利用SocketServer模块来实现网络客户端与服务器并发连接非阻塞通信.首先,先了解下SocketServer模块中可供使用的类:BaseServer:包含服务器的核心功能与混合(mix-in)类 ...