2017-07-30 121 views
0

我正在使用英特尔TBB弄湿我的脚,并试图弄清楚为什么我无法填充通过引用TBB任务传入的矢量,当我还通过了功能通过参考。通过引用TBB任务传递函数时不能返回值

下面是代码:

// tbbTesting.cpp : Defines the entry point for the console application. 

#include "stdafx.h" 

#include "tbb/task.h" 

#include <functional> 
#include <iostream> 
#include <random> 

#define NUM_POINTS 10 


void myFunc(std::vector<double>& numbers) 
{ 
    std::mt19937_64 gen; 
    std::uniform_real_distribution<double> dis(0.0, 1000.0); 

    for (size_t i = 0; i < NUM_POINTS; i++) 
    { 
     auto val = dis(gen); 
     std::cout << val << std::endl; //proper values generated 
     numbers.push_back(val); //why is this failing? 
    } 

    std::cout << std::endl; 

    for (auto i : numbers) 
    { 
     std::cout << numbers[i] << std::endl; //garbage values 
    } 
} 


class TASK_generateRandomNumbers : public tbb::task 
{ 
public: 
    TASK_generateRandomNumbers(std::function<void(std::vector<double>&)>& fnc, 
std::vector<double>& nums) : _fnc(fnc), _numbers(nums) {} 
    ~TASK_generateRandomNumbers() {}; 

    tbb::task* execute() 
    { 
     _fnc(_numbers); 
     return nullptr; 
    } 

private: 
    std::function<void(std::vector<double>&)>& _fnc; 
    std::vector<double>& _numbers; 
}; 


class Manager 
{ 
public: 
    Manager() { _numbers.reserve(NUM_POINTS); } 
    ~Manager() {} 

    void GenerateNumbers() 
    { 
     _fnc = std::bind(&myFunc, _numbers); 
     TASK_generateRandomNumbers* t = new(tbb::task::allocate_root()) 
     TASK_generateRandomNumbers(_fnc, _numbers); 
     tbb::task::spawn_root_and_wait(*t); 
    } 

    auto GetNumbers() const { return _numbers; } 

private: 
    std::function<void(std::vector<double>&)> _fnc; 
    std::vector<double> _numbers; 
}; 



int main() 
{ 
    Manager mgr; 
    mgr.GenerateNumbers(); 
    auto numbers = mgr.GetNumbers(); //returns empty 
} 

execute方法执行操作,我可以通过引用传递载体时获得的值。

execute方法必须调用一个函数,我得到垃圾数据打印到控制台(push_back失败?),我得到一个空的容器返回。

任何人都可以看到我失踪了吗?谢谢。

+0

您是否需要将_numbers传递给使用std :: ref的绑定?否则,我认为你会通过价值传递。 –

回答

1

我发现了一些与tbb无关的bug。

1)您的myFunc使用的范围不正确。它不会返回索引,但每个值都会直接在向量中。你的代码将每个double转换为一个int,并将其用作数组中的索引,这就是为什么gettign垃圾。

2)当你使用std :: bind来创建一个函子时,参数被按值复制。如果你想传入一个引用,那么你需要使用std :: ref来包装参数。

如果您使用的是C++ 11,那么您可能需要考虑使用lambda而不是绑定。

我用不同的方式使用你的myFunc编写了一个小程序:使用和不使用std :: ref和lambda示例。你应该看到它产生了3次相同的数字,但是当它试图打印出v1时,它不会包含任何东西,因为生成的值被放置在一个副本中。

#include <vector> 
#include <random> 
#include <iostream> 
#include <functional> 

constexpr size_t NUM_POINTS = 10; 

void myFunc(std::vector<double>& numbers) 
{ 
    std::mt19937_64 gen; 
    std::uniform_real_distribution<double> dis(0.0, 1000.0); 

    for (size_t i = 0; i < NUM_POINTS; i++) 
    { 
     auto val = dis(gen); 
     std::cout << val << std::endl; //proper values generated 
     numbers.push_back(val); //why is this failing? it's not 
    } 

    std::cout << std::endl; 
} 

void printNumbers(std::vector<double>const& numbers) 
{ 
    for (auto number : numbers) 
    { 
     std::cout << number << std::endl; 
    } 
    std::cout << std::endl; 
} 

int main() 
{ 
    std::cout << "generating v1" << std::endl; 
    std::vector<double> v1; 
    auto f1 = std::bind(&myFunc, v1); 
    f1(); 
    printNumbers(v1); 

    std::cout << "generating v2" << std::endl; 
    std::vector<double> v2; 
    auto f2= std::bind(&myFunc, std::ref(v2)); 
    f2(); 
    printNumbers(v2); 

    std::cout << "generating v3" << std::endl; 
    std::vector<double> v3; 
    auto f3 = [&v3]() { myFunc(v3); }; //using a lambda 
    f3(); 
    printNumbers(v3); 

    return 0; 
} 
+0

我正在使用C++ 11。感谢您的答案并提供了额外的lambda示例。 – jslmsca