Barrier的使用 线程(thread)和进程(processor) 俩种方法

简介

先以一张简图说明 barrier 


(From Quora)

Barrier 是一个 简易的程序 限制 多进程/多线程 之间冲突, 防止出现 锁死情况 (dead_lock) 以及进程 同时运行冲突

barrier 在线程 和 进程 之中有同样的运行 原理

运行原理

第一步, 为了达到 多线程/进程 我们需要一个 通用变量

            这种 通用变量  以很多形式存在与 程序里面:  Gobal 变量 , mmap() 一个虚拟量, 或者是一个打开的 输出文件

先以 sem_h 的方法为例子 去讲解 barrier, 

typedef struct barrier {
    sem_t barrier;
    sem_t mutex;
    int   count;
    int   seen;

} barrier;
#include <semaphore.h>

semaphore 意思是一种信号 传递程序之间是否运行 运行

barrier*
make_barrier(int nn)
{
    int rv;
    barrier* bb = mmap(0, sizeof(barrier), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    if ((long) bb == -1) {
        perror("mmap(barrier)");
        abort();
    }


    rv = sem_init(&(bb->barrier), 1, 0);
    if (rv == -1) {
        perror("sem_init(barrier)");
        abort();
    }


    sem_init(&(bb->mutex), 1, 1);
    if (rv == -1) {
        perror("sem_init(mutex)");
        abort();
    }


    bb->count = nn;
    bb->seen  = 0;
    return bb;
}

sem_init

int sem_init(sem_t *sem, int pshared, unsigned int value);
*sem  sem产量 的地址

pshared  是否允许共享 值为0意思 可以共享在 线程之间 其余的值则是允许共享在不同进程中间

value 初始一个初始数值 

Return 运行成功,输出0

void
barrier_wait(barrier* bb)
{
    int rv;


    rv = sem_wait(&(bb->mutex));
    if (rv == -1) {
        perror("sem_wait(mutex)");
        abort();

    }


    bb->seen += 1;
    int seen = bb->seen;


    rv = sem_post(&(bb->mutex));
    if (rv == -1) {
        perror("sem_post(mutex)");
        abort();
    }


    if (seen >= bb->count) {
        for (int ii = 0; ii < bb->count; ++ii) {
            rv = sem_post(&(bb->barrier));
            if (rv == -1) {
                perror("sem_post(barrier1)");
                abort();
            }
        }
    }


    rv = sem_wait(&(bb->barrier));
    if (rv == -1) {
        perror("sem_wait(barrier)");
        abort();
    }
}

这个barrier 设计是 检查是否所有进程运行完善

count 等于所有进程个数

seen 等于所有完成进程个数

如果 不相等 barrier 会阻止程序运行 反之亦然


int sem_wait(sem_t *sem);

 如果 sem 的值大于 0, 这个方程 锁住 sem 

int sem_post(sem_t *sem);

如果 sem 等于 0, 解锁.

===============================================

如何使用

首先 在运行 fork()划分多进程之前 

make_barrier()

当进程要一起更改 一个 参数的之前

放置

barrier_wait()

会检测是否所用进程 都完成之前的工作 导致不会出现 同时性 运动.

// 最后别忘了 free 哦


Thread Barrier 代码

相同的原理

不过不适用 sem 与之代替的是 直接用 pthread, 更有效率

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>


#include "barrier.h"


// create a barrier, initialize all elements in the barrier, two threads,
// count shuold equal to the size of array, and seen is the waiting number
// of threads.
barrier*
make_barrier(int nn)
{
  int rv;
    barrier* bb = malloc(sizeof(barrier));


    if ((long) bb == -1) {
      perror("malloc(barrier)");
      abort();
  }


      rv = pthread_mutex_init(&(bb->mutex), 0);
  if (rv != 0) {
      perror("pthread_mutex_init(mutex)");
      abort();
  }


      rv = pthread_cond_init(&(bb->condv), 0);
  if (rv != 0) {
      perror("pthread_cond_init(condv)");
      abort();
  }


    bb->count = nn;
    bb->seen  = 0;
    return bb;
}


// put the function before each local array save into output file. it can
// check all thread completion, then, the lock would be unlock satues.
void
barrier_wait(barrier* bb)
{
  pthread_mutex_lock(&bb->mutex);
  bb->seen++;


  if(bb->count != bb->seen) {
    pthread_cond_wait(&bb->condv, &bb->mutex);
  } else {
    pthread_cond_broadcast(&bb->condv);
  }


  pthread_mutex_unlock(&bb->mutex);
}


void
free_barrier(barrier* bb)
{
    free(bb);
}
#原创

#如有问题询问作者

#点赞收藏 哈哈哈

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在CUDA编程中,m_barrier和named barrier是两种常用的线程同步机制,它们可以有效地协调线程之间的合作和同步,提高程序的并行性和效率。 1. m_barrier m_barrier是一种基于硬件实现的线程同步机制,它可以让所有线程在同一时刻停止执行,直到所有线程都到达barrier点。m_barrier使用非常简单,只需要在需要同步的地方调用cudaDeviceSynchronize()函数即可: ``` cudaDeviceSynchronize(); ``` 这样,所有线程都会在该语句处停止执行,直到所有线程都执行完该语句后,才会继续执行下一条语句。 需要注意的是,m_barrier的性能可能受到线程数的影响,因为它需要等待所有线程都到达barrier点才能继续执行。 2. named barrier named barrier是一种基于软件实现的线程同步机制,它可以让不同线程块之间进行同步,提高程序的并行性和效率。named barrier需要先创建一个barrier对象,然后在需要同步的地方调用barrier.sync()函数进行同步。 例如,可以使用以下代码创建一个named barrier对象: ``` cuda::barrier<cuda::thread_scope_block> my_barrier(blockDim.x); ``` 其中,cuda::thread_scope_block表示线程块作用域,blockDim.x表示线程块的大小。 然后,可以在需要同步的地方调用my_barrier.sync()函数进行同步: ``` my_barrier.sync(); ``` 需要注意的是,named barrier的性能可能受到线程块数的影响,因为它需要等待所有线程块都到达barrier点才能继续执行。 总的来说,m_barrier和named barrier都是重要的线程同步机制,在CUDA编程中应用广泛。需要根据具体情况选择合适的同步机制,并进行优化以提高程序的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值