2017-07-30 16 views
0

私は自分の足をIntel 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方法は、関数を呼び出す必要がある場合、私は(一backが失敗?)コンソールに印刷されたゴミデータを取得し、私はリターンに空の容器を得ます。

私は行方不明を誰も見ることができますか?ありがとう。

+0

std :: refを使用して_numbersをbindに渡す必要がありますか?それ以外の場合、私はあなたが価値あるものになると思います。 –

答えて

1

私はtbbとは関係のないいくつかのバグを発見しました。

1)myFuncが誤って範囲を使用しています。インデックスを返すのではなく、ベクトルの各値を順番に返します。あなたのコードは、それぞれのdoubleをintにキャストし、それを配列のインデックスとして使用します。そのため、あなたはgettignのゴミです。

2)std :: bindを使用してファンクタを作成する場合、引数は値によってコピーされます。参照を渡す場合は、引数をラップするためにstd :: refを使用する必要があります。

C++ 11を使用している場合は、バインドではなくラムダの使用を検討してください。

私はあなたの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を使用しています。答えをいただき、追加のラムダの例を提供していただきありがとうございます。 – jslmsca

関連する問題