【问题标题】:Is it possible to multithread to execute non-void functions at the same time? (C++)是否可以多线程同时执行非 void 函数? (C++)
【发布时间】:2017-08-20 21:34:50
【问题描述】:

假设我有一个函数,它对一个向量进行对数变换,乘以一个常数,因此我定义了一个映射函数,给定向量和常数......

vector<double> logtransform(vector<double> &data, int constant){
    vector<double> image;
    for (int i = 0; i < data.size(); i++){
        image.push_back(constant*log(data[i]));
    }
    return image;
}

给定一个名为“data”的向量,我需要对包含在双精度数组中的不同数量的常量应用“logtransform”函数,但是如果函数不是void类型吗?

【问题讨论】:

  • 类型与什么有什么关系?
  • 首先,你应该在向量中至少有reservedata.size() 元素。这里最好将向量resize,然后只需将转换后的值分配给向量中的每个位置。这现在可以并行化(使用 OpenMP 或实际创建一个辅助函数来进行就地转换。
  • 在多线程中执行此函数时,您遇到的具体问题是什么?
  • 您可能更愿意剖析您的 for() 循环以由多个内核并行执行,每个内核负责计算 log[data] 的特定范围。

标签: c++ multithreading function concurrency parallel-processing


【解决方案1】:

使用标准库。从std::transform 开始并让它工作:

std::vector<double> image(data.size()); // allocate all elements!
std::transform(data.begin(), data.end(), image.begin(),
    [](double val) { return constant*log(val); });

我认为是对的,但我没有测试过。

一旦你让它工作,并行化它:

std::vector<double> image(data.size()); // allocate all elements!
std::transform(std::execution::par,
    data.begin(), data.end(), image.begin(),
    [](double val) { return constant*log(val); });

并行化它的唯一变化是添加新的第一个参数std::execution::par。这需要 C++17。

【讨论】:

  • 我对 C++17 不太熟悉,也没学过 execution::par,但看起来很有希望。
【解决方案2】:

当其他线程准备好时,您可以使用std::future 从其他线程收集结果,如下所示:

std::vector<double> logtransform(std::vector<double> const& data, int constant)
{
    std::vector<double> image;
    image.reserve(data.size());

    std::transform(std::begin(data), std::end(data), std::back_inserter(image),
        [constant](double d){ return constant * std::log(d); });

    return image;
}

int main()
{
    std::vector<double> data = {0.3, 0.7, 0.9};

    // start a thread to do the transform
    // remember to pass data by reference using std::cref() (constant reference)
    auto future = std::async(std::launch::async, logtransform, std::cref(data), 5);

    // do something else in parallel
    for(auto i = 0; i < 10; ++i)
        std::cout << " " << i;
    std::cout << '\n';

    // collect results
    auto results = future.get(); // will wait if thread not finished

    for(auto d: results)
        std::cout << " " << d;
    std::cout << '\n';
}

注意:需要C++11

函数std::async 启动一个线程来完成这项工作并返回一个std::future,您可以使用它稍后获取结果。

【讨论】:

  • 哇很好的答案。顺便说一句,是否有必要“并行做其他事情”?是否有必要将 for 循环从 0 打印到 9?
  • @MikeChen for 循环只是一个例子。如果您不打算在当前线程中同时进行其他工作,那么创建新线程是没有意义的。该循环就是此类工作的一个示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-23
  • 1970-01-01
相关资源
最近更新 更多