Thread optimized code has weird behaviour
▲ 1 r/Cplusplus+2 crossposts

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;

}
u/Ill_Worldliness6626 — 14 days ago