Reputation: 643
I have some code like this:
void doSth () {// code ...}
vector<string> files_1; // filenames .txt to get text from
vector<string> files_2; // filenames .txt to get text from
// sizes of files_1 and files_2 are ==
mutex m;
// lambda for for_each
auto gogogo= [&](const string& fn1) {
// Comupute other element via pointer arthimetics
// Works only with vector, for, say, deque, use container of struct
const string& fn2 = files_2[&fn1 - files_1.data()];
// do whatever I need in this doSth function
doSth(fn1, fn2);
// avoid doing any real work under the lock to benefit from paralleling
lock_guard<mutex> guard(m);
};
// start threads
for_each(execution::par, files_1.begin(), files_1.end(), gogogo);
Now for_each
statement execute lambda
so many times as files_1.size()
have. If it have 40 it will execute lambda
in for_each
40 times. I want files_1
& files_2
to be executed in for_each
statement 8 by 8 (every next 8 should be called only after previous 8 executed, not everything for once). How could I do that? Do I need to free memory after every 8 ? (RAM is a question if files_1.size()
size is big, thats why I want to do it in the order 8 by 8 ). Ask me if you have any questions.
I use mingw64
, g++ 9.2
, visual studio 2017 c++17
, windows 10 os
Now lambda do this :
filename1.txt
filename2.txt
filename3.txt
filename4.txt
filename5.txt
filename6.txt
filename7.txt
filename8.txt
filename9.txt
filename10.txt
filename11.txt
filename12.txt
filename13.txt
filename14.txt
filename15.txt
filename16.txt
filename17.txt
I want it to be executed like this:
filename1.txt
filename2.txt
filename3.txt
filename4.txt
filename5.txt
filename6.txt
filename7.txt
filename8.txt
// Previous 8 files executed successfully, next 8
filename9.txt
filename10.txt
filename11.txt
filename12.txt
filename13.txt
filename14.txt
filename15.txt
filename16.txt
// prev 8 executed, next
filename17.txt
// ...
Upvotes: 0
Views: 50
Reputation: 7983
You have to put for_each()
inside a loop, and give it iterators that are 8 elements apart. Here is a possible solution:
#include <iterator>
...
for(auto i = files_1.begin(); i != files_1.end();) {
auto start = i;
auto end = std::advance(i, std::min(8, std::distance(i, files_1.end()));
for_each(execution::par, start, end, gogogo);
i = end;
}
You can write this more concise by using for_each_n()
and the fact that it returns an iterator to the element after the range it just processed:
for(auto i = files_1.begin(); i != files_1.end();) {
auto count = std::min(8, std::distance(i, files_1.end()));
i = for_each_n(execution::par, i, count, gogogo);
}
Upvotes: 1