在GPU并行编程中,一般情况下,各个处理器都需要了解其他处理器的执行状态,在各个并行副本之间进行通信和协作,这涉及到不同线程间的通信机制和并行执行线程的同步机制。

共享内存“__share__”


CUDA中的线程协作主要是通过共享内存实现的。使用关键字“__share__”声明共享变量,将使这个变量驻留在共享内存中,该变量具有以下特征:

  • 位于线程块的共享存储器空间中
  • 与线程块具有相同的生命周期
  • 仅可通过块内的所有线程访问

对于GPU上启动的每个线程块,CUDA C编译器都将创建该变量的一个副本。 线程块中的每个线程都共享这块内存,但线程却无法看到也不能修改其他线程块的变量副本。 这就使得一个线程块中的多个线程能够在计算上进行通信和协作。而且,共享内存缓冲区驻留在物理GPU上,在访问共享内存时的延迟要远远低于访问普通缓冲区的延迟,使得共享内存的访问非常高效。

线程同步机制“__syncthreads()”


关键字“__share__”只是声明了共享变量,位于同一个线程块中的不同线程都可以访问该变量,如果没有同步机制,将会发生竞态条件 (Race Condition),导致错误的运行结果。
CUDA确保同步的方法是调用“__syncthreads()”。__syncthreads()将确保线程块中的每个线程都执行完 __syncthreads()前面的语句后,才会执行下一条语句。

以下是CUDA和OpenCV的应用中,绘制一幅图像,Grid的尺寸大小是60*60,Block的尺寸大小是10*10,在各个线程块内声明了一个共享变量sharedMem:

#include "cuda_runtime.h"
#include <highgui.hpp> using namespace cv; #define DIM 600 //图像长宽
#define PI 3.1415926535897932f __global__ void kernel(unsigned char *ptr)
{
// map from blockIdx to pixel position
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x; __shared__ float sharedMem[16][16];
const float period = 128.0f;
sharedMem[threadIdx.x][threadIdx.y] =
255 * (sinf(x*2.0f*PI / period) + 1.0f) *
(sinf(y*2.0f*PI / period) + 1.0f) / 4.0f;
__syncthreads(); ptr[offset * 3 + 0] = 0;
ptr[offset * 3 + 1] = sharedMem[15 - threadIdx.x][15 - threadIdx.y];
ptr[offset * 3 + 2] = 0;
} // globals needed by the update routine
struct DataBlock
{
unsigned char *dev_bitmap;
}; int main(void)
{
DataBlock data;
cudaError_t error; Mat image = Mat(DIM, DIM, CV_8UC3, Scalar::all(0)); data.dev_bitmap = image.data;
unsigned char *dev_bitmap; error = cudaMalloc((void**)&dev_bitmap, 3 * image.cols*image.rows);
data.dev_bitmap = dev_bitmap; dim3 grid(DIM / 10, DIM / 10);
dim3 block(10, 10);
//DIM*DIM个线程块
kernel << <grid, block >> > (dev_bitmap); error = cudaMemcpy(image.data, dev_bitmap,
3 * image.cols*image.rows,
cudaMemcpyDeviceToHost); error = cudaFree(dev_bitmap); imshow("__share__ and __syncthreads()", image);
waitKey();
}


如果线程间不加入__syncthreads()同步机制,同一线程块内不同线程访问sharedMem,获取的结果可能是不一样的,生成的图像如下,有散乱的杂点:


加入__syncthreads()同步机制,保证了同一线程块中不同的线程都执行完成__syncthreads()这个集合点之前的部分之后,才继续往下执行,所以不同的线程访问sharedMem获取的结果是一致的,图像无杂散点,是一个规律的排布:


CUDA线程协作之共享存储器“__shared__”&&“__syncthreads()”的更多相关文章

  1. GPU编程自学5 —— 线程协作

    深度学习的兴起,使得多线程以及GPU编程逐渐成为算法工程师无法规避的问题.这里主要记录自己的GPU自学历程. 目录 <GPU编程自学1 -- 引言> <GPU编程自学2 -- CUD ...

  2. 基于 Java 2 运行时安全模型的线程协作--转

    在 Java 2 之前的版本,运行时的安全模型使用非常严格受限的沙箱模型(Sandbox).读者应该熟悉,Java 不受信的 Applet 代码就是基于这个严格受限的沙箱模型来提供运行时的安全检查.沙 ...

  3. java线程系列之三(线程协作)

    本文来自:高爽|Coder,原文地址:http://blog.csdn.net/ghsau/article/details/7433673,转载请注明. 上一篇讲述了线程的互斥(同步),但是在很多情况 ...

  4. JAVA并发-线程协作

    这段时间有点忙,技术博客更新的比较少,今天更新一下相关并发的常用线程协作的类吧. ExecutorService 线程池,用于创造和复用线程,他有几种模式. 我举一个自定义线程池数量的例子如下 Exe ...

  5. Java多线程之线程协作

    Java多线程之线程协作 一.前言 上一节提到,如果有一个线程正在运行synchronized 方法,那么其他线程就无法再运行这个方法了.这就是简单的互斥处理. 假如我们现在想执行更加精确的控制,而不 ...

  6. 第41天学习打卡(死锁 Lock synchronized与Lock的对比 线程协作 使用线程池)

    死锁 多个线程各自占有一些共享资源,并且互相等待其他线程占有的资源才能运行,而导致两个或者多个线程都在等待对方释放资源,都停止执行的情形.某一个同步块同时拥有"两个以上对象的锁"时 ...

  7. GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考

    GPU线程以网格(grid)的方式组织,而每个网格中又包含若干个线程块,在G80/GT200系列中,每一个线程块最多可包含512个线程,Fermi架构中每个线程块支持高达1536个线程.同一线程块中的 ...

  8. CUDA线程

    建议先看看前言中关于存储器的介绍:点击打开链接 线程 首先介绍进程,进程是程序的一次执行,线程是进程内的一个相对独立的可执行的单元.若把进程称为任务的话,那么线程则是应用中的一个子任务的执行.举个简单 ...

  9. 【并行计算-CUDA开发】CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解

    GPU的硬件结构,也不是具体的硬件结构,就是与CUDA相关的几个概念:thread,block,grid,warp,sp,sm. sp: 最基本的处理单元,streaming processor  最 ...

随机推荐

  1. 像Bootstrap一样比较热门的前端框架有哪些

    像Bootstrap一样比较热门的前端框架有哪些 一.总结 一句话总结:框架大同小异,可以多去各自官网看看效果(比较一下各自的不同点(也就是提供的不同的功能)),然后根据需求选择用哪个.我觉得boot ...

  2. [array] leetCode-26. Remove Duplicates from Sorted Array - Easy

    26. Remove Duplicates from Sorted Array - Easy descrition Given a sorted array, remove the duplicate ...

  3. 【u249】新斯诺克

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 斯诺克又称英式台球,是一种流行的台球运动.在球桌上,台面四角以及两长边中心位置各有一个球洞,使用的球分 ...

  4. 【TP SRM 703 div2 500】 GCDGraph

    Problem Statement You are given four ints: n, k, x, and y. The ints n and k describe a simple undire ...

  5. Win10安装后必做的优化,解决磁盘100%占用

    Win10安装后必做的优化,解决磁盘100%占用 01关闭家庭组 控制面板–管理工具–服务– HomeGroup Listener和HomeGroup Provider禁用. 02关闭磁盘碎片整理.自 ...

  6. [D3] Load and Inspect Data with D3 v4

    You probably use a framework or standalone library to load data into your apps, but what if that’s o ...

  7. 9个完整android开源app项目

    一.photoup 介绍: photoup 是一款开源的相册类app,主要功能是将本地图片提交到facebook上去,虽然他的功能和facebook的远程服务相关,但是本身是可以被当作一款 相册应用的 ...

  8. php解析xml字符串

    <?php $content = <<<XML <?xml version="1.0" encoding="UTF-8"?> ...

  9. 百度地图坐标之间的距离php

    function GetDistance($lat1, $lng1, $lat2, $lng2){ define('PI',3.1415926535898); define('EARTH_RADIUS ...

  10. #308 (div.2) B. Vanya and Books

    1.题目描写叙述:点击打开链接 2.解题思路:本题要求统计数位的个数,简单的试验一下发现有例如以下规律:一个n位数的个数有9*(10^n)个.因此全部n位数的数位是n*9*(10^n)个.因此能够利用 ...