我正在为以下并行处理任务编写代码:
std::vector<T>
包含需要处理的数据项- 函数
process_data<T&>
对这样的单个数据项进行处理
在我的软件中,我想为不同类型的T
做这件事,所以我写了一个模板类:
#include <mutex>
#include <thread>
#include <vector>
// Parallel processing class.
template <class T>
class parallel_processing {
public:
// Do parallel processing for all items in the vector.
void do_parallel_processing(std::vector<T>& items,
void (*item_processor)(T&),
size_t thread_count = 1)
{
// Check if we should do sequential processing after all.
if (thread_count <= 1) {
for (size_t i = 0; i < items.size(); i++)
item_processor(items[i]);
return;
}
// Proceed with parallel processing.
item_processor_ptr = item_processor;
items_ptr = &items;
next_item_index = 0;
// Spawn all threads.
std::vector<std::thread> threads;
for (size_t i = 0; i < thread_count; i++)
threads.push_back(std::thread(item_thread_worker));
// The current thread should also work hard. This has an advantage: calling join()
// (see below) blocks the thread, costing time. Method 'item_thread_worker' however
// only returns if all items are processed and thus all threads must also have
// finished (or are busy with their last item...).
item_thread_worker();
// Wait for all threads to finish and call join on them.
for (auto& this_thread : threads)
this_thread.join();
}
private:
// Get the next index to process.
int get_next_item_index()
{
const std::lock_guard<std::mutex> lock(next_item_index_mutex);
// Check if we're already done.
if (next_item_index >= (int)items_ptr->size())
return -1;
// Next index (first return, then increment).
return next_item_index++;
}
// Thread-worker method for items.
void item_thread_worker()
{
int item_index;
// Keep on processing while not all items are processed.
while ((item_index = get_next_item_index()) >= 0)
item_processor_ptr((*items_ptr)[item_index]);
}
// Properties.
std::mutex next_item_index_mutex; // For thread-safe access to 'next_item_index'.
int next_item_index; // Identifies the next item index to process.
void (*item_processor_ptr)(T& items); // The item processing function.
std::vector<T>* items_ptr; // Pointer to the vector with items to be processed.
};
这个想法很简单,当它还不在模板类中,而是单独的函数时,它就起作用了,但当然只能为单个类型T
:编码
- 启动了多个线程,它们都运行相同的辅助方法
- 工作人员从
std::vector<T>
中选择一个要处理的数据项,并调用函数来处理所选的项,直到处理完所有项
编译器(VS2019(抱怨以下行:
threads.push_back(std::thread(item_thread_worker));
'使用&创建指向成员的指针
所以我尝试了threads.push_back(std::thread(&item_thread_worker));
,它给了我错误:
"&":对绑定成员函数表达式""进行非法操作
所以我尝试了各种方法:用()
,用前面的类¶llel_processing<T>::
或¶llel_processing::
,但我得到的都是不同的错误。。。
我对C++的了解显然不足以解决这个问题,我们非常感谢。
由于item_thread_worker
是一个非静态成员函数,因此需要使用一个对象进行调用。
创建线程时,不指定任何对象。这些对象(成为函数内部的this
指针(作为隐藏的"指针"传递;第一个";论点
另一点是,要获得指向成员函数的指针,必须使用指向运算符&
的指针。与非成员函数不同,成员函数不会衰减为指向自身的指针。您需要使用带有类名的完整作用域。
因此,要使用应该在this
对象上调用的非静态成员函数创建线程,需要执行std::thread(¶llel_processing::item_thread_worker, this)
。