简体   繁体   English

使用C ++中的线程按顺序填充向量

[英]Filling a vector in order using threads in C++

I'm attempting to fill a huge double vector (1929x1341, might even get bigger) with data, which right now takes around 10 seconds to do. 我正在尝试用数据填充一个巨大的双向量(1929x1341,甚至可能更大),目前大约需要10秒钟。

for reference, this is the code so far: 供参考,这是到目前为止的代码:

vector<vector<float>> vector1;
for (int x = 0; x < mapWidth; x++) {
    vector<float> vector2;
    for (int y = 0; y < mapHeight; y++) {
        int someNumber = calculateNumber(x,y);
        vector2.push_back(someNumber);
    }
    vector1.push_back(vector2);
}

I'm thinking I should be able to cut down on the work-time by dividing the work over separate threads. 我认为我应该能够通过将工作划分为单独的线程来减少工作时间。 Specifically I could separate the second for-loop into each their own thread. 具体来说,我可以将第二个for循环分为各自的线程。

Unfortunately, I am not good with threads. 不幸的是,我对线程不好。 The main issue is that the vectors needs to be filled in order. 主要问题是必须按顺序填充向量。 So I can't just separate the second vector to their own threads and combine them later, as that would put them into a semi-random order. 因此,我不能只将第二个向量分离到自己的线程中,然后再将它们组合起来,因为那样会使它们变成半随机的顺序。 I've looked into mutex and Condition Variables, but I am not able to find a good solution to this specific problem. 我已经研究了互斥量和条件变量,但是无法找到针对此特定问题的良好解决方案。

Would anyone be willing to help me out here? 有人愿意在这里帮助我吗?

You may do something like: 您可以执行以下操作:

std::vector<std::vector<float>> vector1(mapWidth);
std::vector<std::thread> threads;

for (int x = 0; x < mapWidth; x++) {
    threads.emplace_back([&, x]() {
        for (int y = 0; y < mapHeight; y++) {
            int someNumber = calculateNumber(x, y);
            vector1[x].push_back(someNumber);
        }
    });
}

for (int x = 0; x < mapWidth; x++) {
    threads[x].join();
}

The tricky part here is having a few threads all working at the same time. 这里最棘手的部分是几个线程同时工作。 When one of the threads becomes free another one takes over to create a new vector. 当其中一个线程空闲时,另一个线程接管创建新的向量。

For this std::future is useful because it allows us to synchronize the collection of results shared between threads. 对于此std :: future很有用,因为它允许我们同步线程之间共享的结果集合。 We can start one asynchronous task for each thread and collects its results in a std::future object. 我们可以为每个线程启动一个异步任务,并将其结果收集到std :: future对象中。

For this I used std::async to create the threads: 为此,我使用std :: async创建线程:

#include <queue>
#include <vector>
#include <future>
#include <iostream>

int width = 5;
int height = 3;

float calculateNumber(int x, int y)
{
    return x * y;
}

std::vector<float> fill_info(int x, int height)
{
    std::vector<float> v;
    v.reserve(height);

    for(int y = 0; y < height; ++y)
        v.push_back(calculateNumber(x, y));

    return v;
}

int main()
{
    // our thread limit
    const auto number_of_threads = std::thread::hardware_concurrency();

    // our data container
    std::vector<std::vector<float>> v;

    // queue of asynchronous (shared) results
    std::queue<std::future<std::vector<float>>> q;

    for(int x = 0; x < width; x++)
    {
        if(q.size() >= number_of_threads)
        {
            v.push_back(q.front().get()); // blocks until thread is done
            q.pop();
        }

        q.emplace(std::async(std::launch::async, fill_info, x, height));
    }

    // collect uncollected results
    while(!q.empty())
    {
        v.push_back(q.front().get()); // blocks until thread is done
        q.pop();
    }

    std::cout << v.size()<< '\n';

    for(int x = 0; x < width; ++x)
        for(int y = 0; y < height; ++y)
            std::cout << "{" << x << ", " << y << "}: " << v[x][y] << '\n';
}

Output: 输出:

{0, 0}: 0
{0, 1}: 0
{0, 2}: 0
{1, 0}: 0
{1, 1}: 1
{1, 2}: 2
{2, 0}: 0
{2, 1}: 2
{2, 2}: 4
{3, 0}: 0
{3, 1}: 3
{3, 2}: 6
{4, 0}: 0
{4, 1}: 4
{4, 2}: 8

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM