synchronizing 10 threads with atomic bool - c++

I'm trying to use 10 threads and each one needs to print his number and the printing needs to be synchronized. I'm doing it as homework and I have to use atomic variables to do it (no locks).
Here what I tried so far:
#include <atomic>
#include <thread>
#include <iostream>
#include <vector>
using namespace std;
atomic<bool> turn = true;
void print(int i);
int main()
{
vector<thread> threads;
for (int i = 1; i <= 10; i++)
{
threads.push_back(thread(print, i));
}
for (int i = 0; i < 10; i++)
{
threads[i].join();
}
return 0;
}
void print(int i)
{
bool f = true;
for (int j = 0; j < 100; j++)
{
while((turn.compare_exchange_weak(f, false)) == false)
{ }
cout << i << endl;
turn = turn.exchange(true);
}
}
output example:
24
9143
541
2
8
expected output:
2
4
9
1
4
3
1
5
4
10
8

You have 2 bugs in your use of atomic.
When compare_exchange_weak fails it stores the current value in the first parameter. If you want to keep trying the same value you need to set it back to the original value:
while ((turn.compare_exchange_weak(f, false)) == false)
{
f = true;
}
The second issue is that exchange returns the currently stored value so:
turn = turn.exchange(true);
Sets the value of turn back to false, you need just:
turn.exchange(true);
Or even just:
turn = true;
Synchronisation isn't actually necessary in this case as std::cout will do the synchronisation for you, single output operations wont overlap so you can just change your print function to the following and it will just work:
void print(int i)
{
for (int j = 0; j < 100; j++)
{
cout << std::to_string(i) + "\n";
}
}
Atomics aren't the right approach to this problem, your code is incredibly slow. Mutexes would probably be quicker.

Related

Selection Sort Implementation with C++ incorrect

really new to C++, trying to instantiate some basic algorithms with it. Having trouble returning the correct result for selection sort. Here is my code
#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Selection Sort :
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
return m;
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void selectionSort(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); ++i)
{
int min = findMin(arr, i);
swap(arr[i], arr[min]); // Assume a correct swap function
}
}
}
void print(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << "";
cout << endl;
}
}
}
int main()
{
vector<int> sort;
sort.push_back(2);
sort.push_back(1);
sort.push_back(7);
sort.push_back(4);
sort.push_back(5);
sort.push_back(3);
print(sort);
cout << "this was unsorted array";
cout << endl;
cout << findMin(sort, 0);
cout << "this was minimum";
cout << endl;
selectionSort(sort);
print(sort);
}
I am getting the following results:
comparison_sort.cpp:20:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
2
1
7
4
5
3
this was unsorted array
1
this was minimum
1
2
4
5
3
0
My question is: What is causing this control path error? Why is the "7" here being replaced with a "0"?
Thanks in advance! Sorry for the noob question.
I have reviewed all my current functions and nothing seems to explain why the 7 is replaced with a 0. I have tried multiple integers and it looks like the maximum number is always replaced.
The warning is very real, and it alludes to the problem that's breaking your sort as well.
You are currently returning m inside your loop body. What that means is that if the loop is entered, then the function will return m on the very first time around the loop. It only has a chance to check the first element.
And of course, if a is the last index of the array, then the loop will never execute, and you will never explicitly return a value. This is the "control path" which does not return a value.
It's quite clear that you've accidentally put return m; in the wrong place, and even though you have good code indentation, some inexplicable force is preventing you from seeing this. To fix both the warning and the sorting issue, move return m; outside the loop:
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
}
return m;
}

Why does the compiler skip the for-loop?

I have tried to do some practice with vector, and I made a simple for loop to calculate the sum of the elements within the vector. The program did not behave in the way I expect, so I try to run a debugger, and to my surprise, somehow, the compiler skips the for loop altogether, and I have not come up with a reasonable explanation.
//all code is written in cpp
#include <vector>
#include <iostream>
using namespace std;
int simplefunction(vector<int>vect)
{
int size = vect.size();
int sum = 0;
for (int count = 0; count == 4; count++) //<<--this for loop is being skipped when I count==4
{
sum = sum + vect[count];
}
return sum; //<<---the return sum is 0
}
int main()
{
vector<int>myvector(10);
for (int i = 0; i == 10; i++)
{
myvector.push_back(i);
}
int sum = simplefunction(myvector);
cout << "the result of the sum is " << sum;
return 0;
}
I have done some research, and usually the ill-defined for loop shows up when the final condition cannot be met (Ex: when setting count-- instead of count++)
Your loop's conditions are wrong, as they are always false!
Look at to the loops there
for (int i = 0; i == 10; i++)
// ^^^^^^^-----> condition : is it `true` when i is 0 (NO!!)
and
for (int count=0; count==4; count++)
// ^^^^^^^^^-----> condition : is it `true` when i is 0 (NO!!)
you are checking i is equal to 10 and 4 respectively, before incrementing it. That is always false. Hence it has not executed further. They should be
for (int i = 0; i < 10; i++) and for (int count=0; count<4; count++)
Secondly, vector<int> myvector(10); allocates a vector of integers and initialized with 0 s. Meaning, the loop afterwards this line (i.e. in the main())
for (int i = 0; i == 10; i++) {
myvector.push_back(i);
}
will insert 10 more elements (i.e. i s) to it, and you will end up with myvector with 20 elements. You probably meant to do
std::vector<int> myvector;
myvector.reserve(10) // reserve memory to avoid unwanted reallocations
for (int i = 0; i < 10; i++)
{
myvector.push_back(i);
}
or simpler using std::iota from <numeric> header.
#include <numeric> // std::iota
std::vector<int> myvector(10);
std::iota(myvector.begin(), myvector.end(), 0);
As a side note, avoid practising with using namespace std;

What is the fastest way to read from a small (on the order of 10 elements) vector of class pointers in parallel?

    I am looking for the fastest way to have multiple threads reading from the same small vector (one which is not static but will only ever be changed by the main thread and only ever when the child threads are not reading from it) of pointers.
    I've tried using a shared std::vector of pointers which is somewhat faster than a shared array of pointers but still slower per thread... I thought that the reason for that is the threads reading so close together in memory causing false sharing, but I am unsure.
    I'm hoping there is either a way around that since the data is read only when the threads are accessing it or there's an entirely different approach that is faster. Below is a minimal example
#include <thread>
#include <iostream>
#include <iomanip>
#include <vector>
#include <atomic>
#include <chrono>
namespace chrono=std::chrono;
class A {
public:
A(int n=1) {
a=n;
}
int a;
};
void tfunc();
int nelements=10;
int nthreads=1;
std::vector<A*> elements;
std::atomic<int> complete;
std::atomic<int> remaining;
std::atomic<int> next;
std::atomic<int> tnow;
int tend=1000000;
int main() {
complete=false;
remaining=0;
next=0;
tnow=0;
for (int i=0; i < nelements; i++) {
A* a=new A();
elements.push_back(a);
}
std::thread threads[nthreads];
for (int i=0; i < nthreads; i++) {
threads[i]=std::thread(tfunc);
}
auto begin=chrono::high_resolution_clock::now();
while (tnow < tend) {
remaining=nthreads;
next=0;
tnow += 1;
while (remaining > 0) {}
// if {elements} is changed it is changed here
}
complete=true;
for (int i=0; i < nthreads; i++) {
threads[i].join();
}
auto complete=chrono::high_resolution_clock::now();
auto elapsed=chrono::duration_cast<chrono::microseconds>(complete-begin).count();
std::cout << std::setw(2) << nthreads << "Time - " << elapsed << std::endl;
}
void tfunc() {
int sum=0;
int tpre=0;
int curr=0;
while (tnow == 0) {}
while (!complete) {
if (tnow-tpre > 0) {
tpre=tnow;
while (remaining > 0) {
curr=next++;
if (curr > nelements) break;
for (int i=0; i < nelements; i++) {
if (i != curr) {
sum += elements[i] -> a;
}
}
remaining--;
}
}
}
}
Which for nthreads between 1 and 10 on my system outputs (the times are in microseconds)
1 Time - 281548
2 Time - 404926
3 Time - 546826
4 Time - 641898
5 Time - 714259
6 Time - 812776
7 Time - 922391
8 Time - 994909
9 Time - 1147579
10 Time - 1199838
I am wondering if there is a faster way to do this or if such a parallel operation will always be slower than serial due to the smallness of the vector.

How to create a certain number of threads based on a value a variable contains?

I have a integer variable, that contains the number of threads to execute. Lets call it myThreadVar. I want to execute myThreadVar threads, and cannot think of any way to do it, without a ton of if statements. Is there any way I can create myThreadVar threads, no matter what myThreadVar is?
I was thinking:
for (int i = 0; i < myThreadVar; ++i) { std::thread t_i(myFunc); }, but that obviously won't work.
Thanks in advance!
Make an array or vector of threads, put the threads in, and then if you want to wait for them to finish have a second loop go over your collection and join them all:
std::vector<std::thread> myThreads;
myThreads.reserve(myThreadVar);
for (int i = 0; i < myThreadVar; ++i)
{
myThreads.push_back(std::thread(myFunc));
}
While other answers use vector::push_back(), I prefer vector::emplace_back(). Possibly more efficient. Also use vector::reserve(). See it live here.
#include <thread>
#include <vector>
void func() {}
int main() {
int num = 3;
std::vector<std::thread> vec;
vec.reserve(num);
for (auto i = 0; i < num; ++i) {
vec.emplace_back(func);
}
for (auto& t : vec) t.join();
}
So, obvious the best solution is not to wait previous thread to done. You need to run all of them in parallel.
In this case you can use vector class to store all of instances and after that make join to all of them.
Take a look at my example.
#include <thread>
#include <vector>
void myFunc() {
/* Some code */
}
int main()
{
int myThreadVar = 50;
std::vector <thread> threadsToJoin;
threadsToJoin.resize(myThreadVar);
for (int i = 0; i < myThreadVar; ++i) {
threadsToJoin[i] = std::thread(myFunc);
}
for (int i = 0; i < threadsToJoin.size(); i++) {
threadsToJoin[i].join();
}
}
#include <iostream>
#include <thread>
void myFunc(int n) {
std::cout << "myFunc " << n << std::endl;
}
int main(int argc, char *argv[]) {
int myThreadVar = 5;
for (int i = 0; i < myThreadVar; ++i) {
std::cout << "Launching " << i << std::endl;
std::thread t_i(myFunc,i);
t_i.detach();
}
}
g++ -std=c++11 -o 35106568 35106568.cpp
./35106568
Launching 0
myFunc 0
Launching 1
myFunc 1
Launching 2
myFunc 2
Launching 3
myFunc 3
Launching 4
myFunc 4
You need to store the thread so you can send it to join.
std::thread t[myThreadVar];
for (int i = 0; i < myThreadVar; ++i) { t[i] = std::thread(myFunc); }//Start all threads
for (int i = 0; i < myThreadVar; ++i) {t[i].join;}//Wait for all threads to finish
I think this is valid syntax, but I'm more used to c so I am unsure if I initialized the array correctly.

Sieve of Eratosthenes C++ Implementation: not exiting loop

I'm trying to implement the Sieve by myself and with no help other than the algorithm provided...
#include <iostream>
using namespace std;
void findPrimeNumbers(int number) {
int n=0;
bool* boolArray = new bool[number]();
for(int i=0; i<number; i++) {
boolArray[i] = true;
}
for(int i = 2; i<(int)sqrt(number); i++) {
cout << "calculating...\n";
if(boolArray[i]) {
for(int j=(i^2+(n*i)); j<number; n++)
boolArray[j] = false;
}
if(boolArray[i])
cout << i << "\n";
}
return;
}
int main()
{
findPrimeNumbers(55);
system("pause");
return 0;
}
Except the program is hanging on line 37; specifically, "boolArray[j] = false". It's never exiting that loop, and I don't know why.
Edited: Ok, this fixes the hang but still isn't right, but don't answer, I want to figure it out :)
#include <iostream>
#include <cmath>
using namespace std;
void findPrimeNumbers(int number) {
int n=0;
bool* boolArray = new bool[number]();
for(int i=0; i<number; i++) {
boolArray[i] = true;
}
for(int i = 2; i<sqrt(number); i++) {
if(boolArray[i]) {
for (int j = pow(i,2) + n*i; j <= number; j = pow(i, 2) + (++n*i))
boolArray[j] = false;
}
if(boolArray[i] && number % i == 0)
cout << i << "\n";
}
return;
}
int main()
{
findPrimeNumbers(13195);
system("pause");
return 0;
}
Beyond the error pointed out by #Rapptz (^ is bitwise xor), you are incrementing n instead of j, so the termination condition is never reached.
Two problems:
The ^ operator is not the exponent operator like it is in some other languages. Just multiply i by itself instead (i*i).
your for loop:
for(int j=(i^2+(n*i)); j<number; n++)
boolArray[j] = false;
does not reevaluate the initial condition each loop. You need to reevaluate the condition at the beginning of the for loop:
for(int n=0; j<number; n++)
{
j=(i*i+(n*i));
boolArray[j] = false;
}
Your issue is the line i^2+(n*i) like the comments point out, operator^ is the XOR operator, not exponentiation. In order to exponentiate something you have to include the <cmath> header and call std::pow(a,b) where it is equivalent to the mathematical expression a^b.
Although you didn't ask for code review, it should be noted that using dynamic allocation for a bool array is probably not a good idea. You should use std::vector<bool> and a proper reserve call. It should also be noted that the pow call would be completely unnecessary, as you are only multiplying it by itself (i.e. 2^2 is the same as 2*2).
A better naive prime sieve would be something similar to this:
#include <vector>
#include <iostream>
template<typename T>
std::vector<T> generatePrimes(unsigned int limit) {
std::vector<T> primes;
std::vector<bool> sieve((limit+1)/2);
if(limit > 1) {
primes.push_back(2);
for(unsigned int i = 1, prime = 3; i < sieve.size(); ++i, prime += 2) {
if(!sieve[i]) {
primes.push_back(prime);
for(unsigned int j = (prime*prime)/2; j < sieve.size(); j += prime)
sieve[j] = true;
}
}
}
return primes;
}
int main() {
std::vector<unsigned> primes = generatePrimes<unsigned>(1000000);
for(auto& i : primes)
std::cout << i << '\n';
}
You can see it here.
You have a number of problems:
int j=(i^2+(n*i))
^ is not power in C++, it's the bitwise XOR operator. To fix this, you'll need to #include <cmath> and utilize pow, or simply use i * i.
Secondly, as others have mentioned, you are incrementing n. The easiest fix for this is to use a while loop instead:
int j = std::pow(i, 2) + (n*i);
while(j < number) {
//Set bool at index to false
j += i;
}
Thirdly, you have a memory leak - you new without a delete. Further, there's no reason to use new here, instead you should have:
bool b[number];
This will deallocate b automatically when the function exits.
Finally, why return at the bottom of a void function? Technically you can do it, but there is no reason to.