是否可以多线程同时执行非 void 函数? (C++)

Posted

技术标签:

【中文标题】是否可以多线程同时执行非 void 函数? (C++)【英文标题】:Is it possible to multithread to execute non-void functions at the same time? (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] 的特定范围。 【参考方案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 循环只是一个例子。如果您不打算在当前线程中同时进行其他工作,那么创建新线程是没有意义的。该循环就是此类工作的一个示例。

以上是关于是否可以多线程同时执行非 void 函数? (C++)的主要内容,如果未能解决你的问题,请参考以下文章

多线程

C/C++多线程

Visual C++ 如何使用线程启动非 void 函数

iOS多线程编程之锁的理解

c语言怎么创建线程和使用

iOS 多线程GCD的基本使用