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?
有人愿意帮助我吗?
2 个解决方案
#1
1
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();
}
#2
1
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. We can start one asynchronous task for each thread and collects its results in a std::future object.
对于这个std :: future非常有用,因为它允许我们同步线程之间共享的结果集合。我们可以为每个线程启动一个异步任务,并在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
#1
1
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();
}
#2
1
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. We can start one asynchronous task for each thread and collects its results in a std::future object.
对于这个std :: future非常有用,因为它允许我们同步线程之间共享的结果集合。我们可以为每个线程启动一个异步任务,并在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