2014-01-09 44 views
2

首先我做了一个线程池,并试图对一个大小为40960个float元素的数组做一些重算术运算。C++ 11并行执行

单线程方法得到0.0009秒的结果,而同时运行4线程的并行方法得到0.0003秒。在这个实现中,我手动将任务分配到4个部分,并将它们排入线程池。

现在我想为我的线程池提供一个通用方法parfor。我试过这个:

void parfor(int begin, int end, std::function<void(int)>func) 
    { 
     int delta = (end - begin)/M_count; 
     for (int i = 0; i < M_count; ++i) 
      queue([=]{ 
       int localbegin = begin + i*delta; 
       int localend = (i == M_count - 1) ? end : localbegin + delta; 
       for (int it = localbegin; it < localend; ++it) 
        func(it); 
      }); 
     wait(); 
    } 

其中M_count是线程数。执行时间变为0.003秒(大约是手工分发作业的10倍)。我想std ::函数有一个很好的运行时间开销,但不知道任何其他的替代方法。你能给我一些建议吗?非常感谢。

编辑: 根据Rapptz的建议,我尝试这样做:

template <typename Function> 
void parfor(int begin, int end, Function) 

,并用它是这样的:

pool.parfor(0, 40960, [&](int i){ 
    buff[i] = pow5(buff[i]); 
}); 

它显示了一些错误:

error C2371: 'it' : redefinition; different basic types 
error C2512: 'wmain::<lambda_badf06dfbebc4bb15b3ade2b922c7f76>' : no appropriate default constructor available 

我想它将lambda视为一种类型,但不知道如何解决它...

+0

也许你的手动版本可以内联函数,而'parfor'显然不能。 – woolstar

+2

使用模板而不是'std :: function'。 – Rapptz

+0

@woolstar是的,我想是的。但不知道如何在我的parfor中强制内联函数。 – babel92

回答

2

(太多评论...)这只是解释如何实现Rapptz使用模板参数来指定函数(因此可以内联)的建议。

考虑下面的代码:

#include <iostream> 

void f(int n) { std::cout << "f(" << n << ");\n"; } 
void g(int n) { std::cout << "g(" << n << ");\n"; } 

template <typename Function> 
void t(Function function, int n) 
{ 
    static int x; 
    std::cout << "&x " << &x << '\n'; 
    function(n); 
} 

struct FuncF { static void f(int n) { std::cout << "Ff(" << n << ");\n"; } }; 
struct FuncG { static void f(int n) { std::cout << "Gf(" << n << ");\n"; } }; 

template <typename Function> 
void ft(int n) 
{ 
    static int x; 
    std::cout << "&x " << &x << '\n'; 
    Function::f(n); 
} 

int main() 
{ 
    t(f, 42); 
    t(g, 42); 

    ft<FuncF>(42); 
    ft<FuncG>(42); 
} 

这将打印类似:

&x 00421760 
f(42); 
&x 00421760 
g(42); 
&x 00421764 
Ff(42); 
&x 00421768 
Gf(42); 

注意的是,前两个打印相同的地址x ...这是因为只有一个实例化的模板因为这两个调用的函数类型是相同的。 ft模板使用模板参数访问该函数而不涉及运行时函数参数,因此有两个实例产生本地静态的不同地址x

要使您的函数调用内联,您应该采用类似于FuncF/FuncGft的方法。

+0

谢谢!这太棒了,它的工作原理!我刚刚回想起这是类似functor ...但是让我不高兴的是单线程代码运行速度比我的parfor下发布速度更快...... – babel92

+0

@ babel92:好吧,40960不是很多浮点数,而0.0009是一个线程启动/同步之后很难打败。如果您能够使用CPU或GPU指令进行并行实数处理(我从来没有使用它们,但认为有一些引入了MMX和/或SSE CPU指令集添加),您可能会得到更好的结果。 –

+0

将数组增加到409600后,线程的优势变得明显:)实际上,这只是一个实验。非常感谢。 – babel92