我有一个 main.cpp 文件,其中包含以下代码
paral(start, end, [&](int i){
C1[i] = A1[i] + B[i];
}, numThreads);`
我在 otherfile.cpp 中有 paral
定义,其中有以下代码
void paral(int start, int end, T &&lambda, int nT){
pthread_t thread1;
int status = pthread_create(&thread1, NULL,lambda ,1);//Should execute lambda(1)
lambda(2);//Executed by main thread
//Code for join and so on
}
它说:
can't covert lambda to (void*)(*)(void *).
我尝试将 lambda 函数强制转换并传递给 pthread,但这没有帮助。 我也想从创建的线程调用 lambda 函数,但我无法做到。
最佳答案
首先您必须了解 Lambda 是一个对象,它实现 operator()(args...)
成员函数。在您的具体情况下,它是operator()(int i)
。
为了执行此 lambda,必须将两个参数传递给 operator()(int)
:
- Lambda 指针(
this
) - 整数
lambda 的地址是对象(即数据)的地址,而不是代码的地址。
线程启动函数是一个接受void*
并返回void*
的函数。函数地址是机器代码的地址。
因此,要执行 lambda,您应该定义 void* (void*)
函数并将其地址作为 start_routine
参数传递。作为 arg 参数传递的 lambda 地址:
template<typename Lambda>
void paral(int start, int end, Lambda&& lambda, int nT){
struct Args
{
int Start;
int End;
Lambda& Func;
};
// create captureless lambda
auto threadStart = +[](void* voidArgs) -> void*
{
auto& args = *static_cast<Args*>(voidArgs);
for(int i = args.Start; i < args.End; ++i)
args.Func(i);
return nullptr;
};
// I create one thread here. You will create more.
auto args = Args{start, end, lambda};
pthread_t handle;
int rc = pthread_create(&handle, NULL, threadStart, &args);
if(rc)
throw std::system_error(
std::error_code(rc, std::generic_category()),
"pthread_create");
pthread_join(handle, nullptr);
}
但是在这种特定情况下,您最好使用 std::thread
而不是 pthread
库。在这种情况下,您的代码可能如下所示:
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
template<typename Func>
void paral(int start,
int end,
Func &&func,
int threads_count = std::thread::hardware_concurrency())
{
std::atomic_int counter {start};
std::vector<std::thread> workers;
workers.reserve(threads_count);
for(int i = 0; i < threads_count; ++i) {
workers.emplace_back([end, &counter, &func] {
for(int val = counter++; val < end; val = counter++)
func(val);
});
}
for(int i = 0; i < threads_count; ++i)
workers[i].join();
}
int main() {
int C1[10];
int A[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int B[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 110};
paral(0, 10, [&](int i){ C1[i] = A[i] + B[i]; });
for(auto&& v: C1)
std::cout << v << "\n";
std::cout << "Done. Bye!" << std::endl;
}
不过有重要说明。您的代码的运行速度可能不如您预期的那么快。它将经历false sharing问题是,多个线程修改同一缓存线的内存,这将迫使 CPU 核心在每次另一个 CPU 核心更新内存时都更新其 L1 缓存。
另请参阅:
关于c++ - 如何修复: Executing lambda expression using pthread in c++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54069445/