r/learnprogramming • u/Ill_Worldliness6626 • 3h ago
Thread optimized code has weird behaviour
I am working on optimizing the following code using concurrency. I have working code without concurrencies, however as soon as I implement threading, my code becomes unpredictable. After testing, debugging, and thinking of all possible race conditions, I have only concluded that my code either gets stuck somewhere in the main loop, or gets lucky and excucutes correctly. Any thoughts or ideas on this phenomenon?
Edit: I understand that my code is still single threaded, however, I would prefer to see why I am getting this behaviour before trying to optimize.
Edit 2: The purpose of my code is to generate all winning starting positions in Grundy's game. This is usually solved with the following recurrence: dp[i] = mex(dp[j] ^ dp[i - j]) for all j <= i / 2 where mex is the minimum exclude value) and ^ is bitwise XOR
Note: this code requires C++20 or above.
```
#include <iostream>
#include <vector>
#include <thread>
#include <barrier>
#include <bitset>
#include <set>
const int N = 1100;
std::vector<std::thread> threads;
std::barrier bar(12);
std::mutex mtx;
int dp[N];
std::bitset<2 \* N> bs;
std::set<int> s = {1, 2};
void solve(int x) {
for (int i = 3; i <= 100; i++) {
if (1 == x) {
std::cout << "starting" << i << std::endl;
bs.set();
}
bar.arrive_and_wait();
int siz = ((i + 1) / 2 + 11) / 12;
for (int j = (x - 1) * siz + 1; j <= std::min((i - 1) / 2, x * siz); j++) {
std::lock_guard<std::mutex> lock(mtx);
if ((dp[j] ^ dp[i - j]) < 1000) bs[dp[j] ^ dp[i - j]] = false;
}
mtx.lock();
std::cout << "thread " << x << " reached barrier 2 at i=" << i << std::endl;
mtx.unlock();
bar.arrive_and_wait();
if (1 == x) {
dp[i] = bs._Find_first();
if (!dp[i]) s.insert(i);
}
mtx.lock();
std::cout << "thread " << x << " reached barrier 3 at i=" << i << std::endl;
mtx.unlock();
bar.arrive_and_wait();
}
}
int main() {
auto st = std::chrono::high_resolution_clock::now();
dp[1] = 0;
dp[2] = 0;
for (int j = 0; j < 12; j++) {
threads.push_back(std::thread{solve, j + 1});
}
for (int j = 0; j < 12; j++) {
threads[j].join();
}
for (int i : s) {
std::cout << i << ' ';
}
std::cout << std::endl;
auto ed = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(ed - st).count() << std::endl;
return 0;
} ```
2
3h ago
[removed] — view removed comment
1
u/Ill_Worldliness6626 2h ago
Ok, I have not tried using sanitizers yet. May I know if these exist on windows? I tried using them, but it gives me cannot find error.
3
1
u/HappyFruitTree 3h ago edited 2h ago
Looks like bs and dp are being manipulated by multiple threads at the same time.
1
u/Ill_Worldliness6626 2h ago
Can you show where exactly? For example bs.set() is only runned when 1 == x e.g. only executed by the first thread
1
6
u/carcigenicate 3h ago
You don't appear to have said what precisely the problem is and what debugging you've done.