Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 非常基本的循环使用TBB_C++_Multithreading_Tbb - Fatal编程技术网

C++ 非常基本的循环使用TBB

C++ 非常基本的循环使用TBB,c++,multithreading,tbb,C++,Multithreading,Tbb,我是一个非常新的程序员,我有一些来自英特尔的例子麻烦。我想如果我能看到最基本的循环是如何在tbb中实现的,那会很有帮助 for (n=0 ; n < songinfo.frames; ++n) { sli[n]=songin[n*2]; sri[n]=songin[n*2+1]; } (n=0;n

我是一个非常新的程序员,我有一些来自英特尔的例子麻烦。我想如果我能看到最基本的循环是如何在tbb中实现的,那会很有帮助

for (n=0 ; n < songinfo.frames; ++n) {  

         sli[n]=songin[n*2];
         sri[n]=songin[n*2+1];

}
(n=0;n
这里有一个循环,我用它来解交织音频数据。这个循环会从tbb中受益吗?您将如何实现它?

首先,对于以下代码,我假设您的
数组
属于
mytype*
类型,否则代码需要一些修改。此外,我假设您的范围没有重叠,否则并行化调度将无法正常工作(至少不需要更多的工作)

既然您在tbb中要求:

首先,您需要在某个地方初始化库(通常在
main
中)。对于代码,假设我在某处放置了一个
使用名称空间tbb

int main(int argc, char *argv[]){
   task_scheduler_init init;
   ...
}
然后需要一个函子来捕获数组并执行forloop的主体:

struct apply_func {
    const mytype* songin; //whatever type you are operating on
    mytype* sli;
    mytype* sri;
    apply_func(const mytype* sin, mytype* sl, mytype* sr):songin(sin), sli(sl), sri(sr)
    {}
    void operator()(const blocked_range<size_t>& range) {
      for(size_t n = range.begin(); n !=range.end(); ++n){
        sli[n]=songin[n*2];
        sri[n]=songin[n*2+1];
      }
    }
}
这样就可以了(如果我没记错的话,我已经有一段时间没看tbb了,所以可能会有一些小错误)。 如果使用c++11,可以通过使用
lambda
简化代码:

size_t grainsize = 1000; //or whatever you decide on (testing required for best performance);
parallel_for(blocked_range<size_t>(0, songinfo.frames, grainsize), 
             [&](const blocked_range<size_t>&){
                for(size_t n = range.begin(); n !=range.end(); ++n){
                  sli[n]=songin[n*2];
                  sri[n]=songin[n*2+1];
                }
             });
然后,您必须告诉编译器编译并链接openmp(
-fopenmp
用于gcc,
/openmp
用于visual c++)。正如您所看到的,它比tbb更易于使用(对于这种简单的用例,更复杂的场景是另一回事),并且具有在不支持openmp或tbb的平台上工作的额外好处(因为未知的
#pragmas
被编译器忽略)。就我个人而言,我在一些项目中使用openmp支持tbb,因为我无法使用它的开源许可证,而购买tbb对于这些项目来说有点过于苛刻

现在我们有了如何并行化循环的方法,让我们来看看这个问题是否值得。这是一个很难回答的问题,因为它完全取决于你处理了多少元素,以及你的程序运行在什么样的平台上。您的问题是带宽非常大,因此我不会指望性能有多大的提高

  • 如果只处理
    1000
    元素,由于开销,并行版本的循环很可能比单线程版本慢
  • 如果您的数据不在缓存中(因为它不适合),并且您的系统非常缺乏带宽,那么您可能看不到多少好处(尽管您可能会看到一些好处,但如果它的顺序是
    1.X
    ,即使您使用了大量处理器,也不会得到支持)
  • 如果您的系统是ccNUMA(可能适用于多socket系统),则由于额外的传输成本,无论元素的数量如何,您的性能都可能会降低
  • 编译器可能会错过有关指针别名的优化(因为循环体已移动到不同的dunction)。使用
    \uu restrict
    (对于gcc,对于vs没有任何线索)可能有助于解决该问题

就个人而言,我认为最有可能看到显著性能提高的情况是,如果您的系统有一个多核cpu,那么数据集可以放入三级缓存(而不是单独的二级缓存)。对于更大的数据集,您的性能可能会提高,但不会提高很多(正确使用预取可能会获得类似的收益)。当然,这是纯粹的规范化。

单词“非常新的程序员”和“线程化”不应该出现在同一句话中。如果你是一个“非常新的程序员”,线程不是你需要关心的事情。现在,您只需要了解
if
for
语句是如何工作的。函数如何工作以及一些基本的内存管理。如何创建和管理对象。虽然TBB确实让线程变得更简单,但线程并不是一门入门课程。我是新手,但在过去一个月左右的时间里,我几乎把所有的空闲时间都花在了学习上,我想我已经掌握了很多基础知识。作为一个学习项目,我正在试验声音处理,我的项目已经基本完成,因此我将采取下一步,并尝试添加多线程以加快部分代码的速度。P
size_t grainsize = 1000; //or whatever you decide on (testing required for best performance);
parallel_for(blocked_range<size_t>(0, songinfo.frames, grainsize), 
             [&](const blocked_range<size_t>&){
                for(size_t n = range.begin(); n !=range.end(); ++n){
                  sli[n]=songin[n*2];
                  sri[n]=songin[n*2+1];
                }
             });
#pragma omp prallel for
for(size_t n = 0; n < songinfo.frames; ++n) {
  sli[n]=songin[n*2];
  sri[n]=songin[n*2+1];
}