如何使用 std::thread 逐行像素多线程?

How to multithread line by line pixels using std::thread?

本文关键字:像素 多线程 逐行 thread 何使用 std      更新时间:2023-10-16

我想学习如何将我用于多线程的伪代码逐行调整为C++。我了解伪代码,但我对C++和std::thread功能不是很有经验。

这是我拥有的伪代码,我经常使用:

myFunction
{
int threadNr=previous;
int numberProcs = countProcessors();
// Every thread calculates a different line
for (y = y_start+threadNr; y < y_end; y+=numberProcs) {
// Horizontal lines
for (int x = x_start; x < x_end; x++) {
psetp(x,y,RGB(255,128,0));
}
}
}
int numberProcs = countProcessors();
// Launch threads: e.g. for 1 processor launch no other thread, for 2 processors launch 1 thread, for 4 processors launch 3 threads
for (i=0; i<numberProcs-1; i++)
triggerThread(50,FME_CUSTOMEVENT,i); //The last parameter is the thread number
triggerEvent(50,FME_CUSTOMEVENT,numberProcs-1); //The last thread used for progress
// Wait for all threads to finished
waitForThread(0,0xffffffff,-1);

我知道我可以通过这样的std::thread使用一个线程调用我当前的函数:

std::thread t1(FilterImage,&size_param, cdepth, in_data, input_worldP, output_worldP);
t1.join();

但这效率不高,因为它在每个线程上一遍又一遍地调用整个函数。

我希望每个处理器都能自己处理一条水平线。

任何示例代码都将不胜感激,因为我倾向于通过示例学习最好。

调用thread::join()会强制调用线程等待子线程完成执行。例如,如果我使用它在循环中创建多个线程,并在每个线程上调用join(),则一切都按顺序发生。

下面是一个示例。我有两种方法可以打印出数字 1 到 n。第一个是单线程的,第二个在创建每个线程时加入每个线程。两者都具有相同的输出,但线程的输出速度较慢,因为您要等待每个线程完成,然后再开始下一个线程。

#include <iostream>
#include <thread>
void printN_nothreads(int n) {
for(int i = 0; i < n; i++) {
std::cout << i << "n";
}
}
void printN_threaded(int n) {
for(int i = 0; i < n; i++) {
std::thread t([=](){ std::cout << i << "n"; });
t.join(); //This forces synchronization
}
}

更好地进行线程处理。

要从使用线程中获益,您必须在加入它们之前启动所有线程。此外,为了避免错误共享,每个线程都应在图像的单独区域(理想情况下是内存中很远的部分)上工作。

让我们看看这将如何工作。我不知道你用的是什么库,所以我将向你展示如何在向量上编写多线程转换。

auto transform_section = [](auto func, auto begin, auto end) {
for(; begin != end; ++begin) {
func(*begin);
}
};

transform_section函数将为每个线程调用一次,每个函数在向量的不同部分上调用。让我们编写transform以便它是多线程的。

template<class Func, class T>
void transform(Func func, std::vector<T>& data, int num_threads) {
size_t size = data.size(); 
auto section_start = [size, num_threads](int thread_index) {
return size * thread_index / num_threads; 
};
auto section_end = [size, num_threads](int thread_index) {
return size * (thread_index + 1) / num_threads; 
};
std::vector<std::thread> threads(num_threads); 
// Each thread works on a different section
for(int i = 0; i < num_threads; i++) {
T* start = &data[section_start(i)];
T* end   = &data[section_end(i)]; 
threads[i] = std::thread(transform_section, func, start, end);
}
// We only join AFTER all the threads are started
for(std::thread& t : threads) {
t.join();
}
}