gpt4 book ai didi

c++ - 在线程函数中使用数据 vector 时发生线程竞赛

转载 作者:行者123 更新时间:2023-12-02 10:31:13 25 4
gpt4 key购买 nike

作为早期的c++ /线程编码器,我在我的测试功能之一中遇到了线程竞速方面的困难,并且将不胜感激。

我的parent()函数将相当大的图像 vector (来自openCV的cv::Mat)作为输入,任务是分别计算每个图像的运算符(例如膨胀)。我编写了一个循环,该循环使用worker()函数创建线程,并在每个线程上传递输入 vector 的子集。

每个线程的结果将存储在该输入子集 vector 上。我的问题是我无法从parent()中找回它。

作为一种替代方法,我将整个 vector 传递给worker(),并为每个线程提供了开始和结束索引,但随后我遇到了一些严重的线程竞速问题,比串行方法耗时更多。

请在下面查看我的代码。

std::vector<cv::Mat> worker(std::vector<cv::Mat>& ctn);
std::vector<cv::Mat> worker(std::vector<cv::Mat>& ctn) {

int erosion_type = cv::MORPH_RECT;
int erosion_size = 5;

cv::Mat element = cv::getStructuringElement( erosion_type,
cv::Size( 2*erosion_size + 1, 2*erosion_size+1 ),
cv::Point( erosion_size, erosion_size ) );

this_mutex.lock();
for(uint it=0; it<ctn.size(); ++it) {
cv::erode(ctn[it], ctn[it], element);
}
this_mutex.unlock();
return ctn;
}


void parent(std::vector<cv::Mat>& imageSet) {

auto start = std::chrono::steady_clock::now();

const auto processor_count = std::thread::hardware_concurrency();

std::vector<std::thread> threads;

const int grainsize = imageSet.size() / processor_count;

uint work_iter = 0;
std::vector<cv::Mat> target; // holds the output vector

// create the threads
for(uint it=0; it<processor_count-1; ++it) {
std::vector<cv::Mat> subvec(imageSet.begin() + work_iter, imageSet.begin() + work_iter + grainsize);
threads.emplace_back([&,it]() {
std::vector<cv::Mat> tmp = worker(subvec);
target.insert(target.end(), tmp.begin(), tmp.end());
});
work_iter += grainsize;
}

// create the last thread for the remainder of the vector elements
std::vector<cv::Mat> subvec(imageSet.begin() + work_iter, imageSet.end());
int it = processor_count-1;
threads.emplace_back([&,it]() {
std::vector<cv::Mat> tmp = worker(subvec);
target.insert(target.end(), tmp.begin(), tmp.end());
});

// join the threads
for(int i=0; i<threads.size(); ++i) {
threads[i].join();
}

auto end = std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";

// try to reconstruct the output
imageSet.clear();
for(int i=0; i<target.size(); ++i) {
imageSet.push_back(target[i]);
}
}

在此代码中,语句 target.insert(target.end(), tmp.begin(), tmp.end())旨在将target [] vector 与每个线程的结果连接在一起,但是它没有及时执行,因此最后得到一个空的target []。

有什么想法如何使target []收集所有tmp []吗?

最佳答案

你在想什么?
这将分别处理它们,但是您可以根据需要将其分块,并根据需要从lamda返回 vector 。
注意:这是在C++ 11中,因为这就是您标记的内容。如果您可以使用17,则变得非常简单。

#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
#include <iostream>

int main()
{
std::vector<int> input{0,1,2,3,4,5,6,7,8,9,10};

for(const auto& item : input)
{
std::cout << item << " ";
}

std::cout << std::endl;

std::vector<std::future<int>> threads{};

for(const auto& item : input)
{
threads.push_back(std::async(std::launch::async, [&item]{
return item * 100;
}));
}

std::vector<int> output{};

for(auto& thread : threads)
{
output.push_back(thread.get());
}

for(const auto& item : output)
{
std::cout << item << " ";
}

return 0;
}

关于c++ - 在线程函数中使用数据 vector 时发生线程竞赛,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62175997/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com