我正在研究多线程C ++ vapply函数,它将函数应用于向量的每个元素。诀窍是我不想为向量中的每个元素创建一个线程;我宁愿创建一定数量的线程,并为每个线程分配一个矢量来处理。
但是,我不确定如何使用std::async
捕获操作的结果。这是我到目前为止所做的:
vapply.h
:
#ifndef VAPPLY_H
#define VAPPLY_H
#include <vector>
#include <thread>
#include <memory>
#include <future>
#include <functional>
class vapply
{
private:
template <class Fn, class T>
auto docall(Fn&& fn, std::vector <T> &v, size_t begin, size_t end)
{
using return_type = typename std::result_of <Fn(T)>::type;
std::vector <return_type> result;
result.reserve(end - begin);
for (size_t i = begin; i < end; i++)
{
result.emplace_back(fn(v[i]));
}
return result;
}
public:
// Constructor
template <class Fn, class T>
vapply(Fn&& fn, std::vector <T> &v)
{
size_t maxNumThreads = std::thread::hardware_concurrency() - 1;
size_t funcPerThread = v.size() / maxNumThreads;
size_t funcModThread = v.size() % maxNumThreads;
size_t funcToPerform = 0;
for (size_t i = 0; i < v.size(); i += funcToPerform)
{
funcToPerform = (i == 0) ? funcPerThread + funcModThread : funcPerThread;
// this line works fine, extract the results of docall
auto p = docall(std::forward <Fn>(fn), v, i, i + funcToPerform);
// now I'd like to do the same thing but in a separate thread, but below doesn't compile
// auto q = std::async(std::launch::async, &vapply::docall, std::forward <Fn>(fn), v, i, i + funcToPerform);
}
}
};
#endif /* VAPPLY_H */
main.cpp
:
#include <iostream>
#include <numeric>
#include <string>
#include "vapply.h"
std::string test1(uint64_t a)
{
return std::to_string(a);
}
int main(int argc, char **argv)
{
std::vector <uint64_t> v(17);
std::iota(v.begin(), v.end(), 0);
vapply(test1, v);
return 0;
}
答案 0 :(得分:1)
auto q = std::async(std::launch::async, &vapply::docall, std::forward <Fn>(fn), v, i, i + funcToPerform);
此行无法编译,因为要将方法作为参数传递给函数,它必须绑定到实例this
。所以使用std::bind
或更好的lambda:auto fut = std::async(std::launch::async, [&] { return docall(std::forward <Fn>(fn), v, i, i + funcToPerform); });
来获得future
的结果get()
使用auto q = fut.get();
这样的方法,但请记住{ {1}}是一个阻塞调用,因此在循环中调用future::get()
然后调用async()
将不会运行多个线程。而是将期货保存在一个循环中,并为其他循环中的每个未来调用get()。