并行编程实战——TBB中消息并行策略的控制

235 篇文章 94 订阅
7 篇文章 0 订阅

一、并行策略

TBB框架本身就是一个并行的框架,那么在节点的消息处理过程中,并行的控制也就是相关的策略一定会有以下几类:
1、缓冲消息
缓冲即将收到的待处理的消息保存在队列(或类似缓存)中,然后再一条条的处理。当然,这个缓存队列仍然是有上限的。
2、丢弃消息
即接收到消息后直接丢弃,不再处理。
3、拒绝消息
即在达到指定条件后,不再接收新的消息。也可以理解为前二者的一个结合体,是一个指定的有限的队列。
在TBB的源码中定义了四个空的类:

    struct rejecting { };//1
    struct reserving { };
    struct queueing  { };//2
    struct lightweight  { };

    template < typename Input,
           typename Output = continue_msg,
           graph_buffer_policy = queueing >
class function_node;

上面四个策略中,与并行有关系的只有1和2,其它两个用来做轻量任务处理和预分配内存机制处理。TBB中只对缓冲和相对受限缓冲(拒绝)感兴趣。从上面的代码可以看出,功能节点中的消息并发控制策略为缓冲队列方式。如果达到了并发策略的上限后,功能节点会把相关的消息缓存到队列中去,待并发下降后再次读取队列进行处理。

二、例程

继续看官网的例子:


int main(){
graph g;


int src_count = 0;
int number_of_objects = 0;
int max_objects = 3;


input_node< big_object * > s( g, [&]( oneapi::tbb::flow_control& fc ) -> big_object* {
    if ( src_count < M ) {
      big_object* v = new big_object();
      ++src_count;
      return v;
    } else {
      fc.stop();
      return nullptr;
    }
} );
s.activate();

//注意下面的continue_msg和受限的3
function_node< big_object *, continue_msg, rejecting > f( g, 3,
    []( big_object *v ) -> continue_msg {
    spin_for(1);
       delete v;
    return continue_msg();
} );


make_edge( s, f );
g.wait_for_all();

return 0;
}

上面使用continue_msg,表示是一个对前驱节点的依赖节点,而在功能节点function_node创建时,使用了rejecting缓冲策略并指定了受限的并发上限为3,即在收到并同时 处理三个消息时(即并发运行三个实例时),它将拒绝从前驱节点接收消息。而在本例程中,前驱的输入节点将缓存最后创建的对象并停止调用其Body对象即其实例函数。而当功能节点处理的当前实例数小于3个时,又可以从前驱节点中获取消息。所以消息的实例对象,最多有四个,即一个在输入节点中,三个在功能节点的处理中。

三、、总结

不同的节点有着不同的处理机制,而实际的应用场景千变万化。到达罗马的大路不止一条,何况还有小路。所以,正确的选择可能有很多,但如果寻找一条更适合当前环境的设计思路,这才是重点。最好不一定合适,合适其实从某种意义上说才是最好。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值