Run method and wait to finish all for loops openmp - c++

I creathed in C++ method to find number's dividors. Second step was to use openmp in c++.
Unfortunatelly I can't manage why my function doStuff throws memory error. Probably the problem is with threads and I check arrays before all threads stop.. Could someone help me?
There is no need to read all my program, the problem is in doStuff()
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include "omp.h"
using namespace std;
vector<int> dividors;
int NUMBER = 1000;
bool ifContains(vector<int> element, int dividedNumber)
{
for(int i=0; i<dividors.size(); i++)
{
if(dividors[i] == dividedNumber)
return true;
}
return false;
}
void doStuff()
{
int sqr = (int) sqrt(NUMBER);
int sqrp1 = sqr + 1;
#pragma omp parallel
{
#pragma omp for nowait
for (int i = 1; i < sqrp1; i++)
{
if (NUMBER % i == 0)
{
if (!ifContains(dividors, i))
dividors.push_back(i);
int dividednumber = NUMBER / i;
if (!ifContains(dividors,dividednumber))
dividors.push_back(dividednumber);
}
}
sort(dividors.begin(), dividors.end());
#pragma omp for nowait
for (int i = 0; i < dividors.size(); i++)
{
cout << dividors[i] << "\r\n";
}
}
}
int main()
{
doStuff();
return 0;
}
Also I tried this, but It doesn't work
void doStuff()
{
int sqr = (int) sqrt(NUMBER);
int sqrp1 = sqr + 1;
#pragma omp parallel
{
#pragma omp for
for (int i = 1; i < sqrp1; i++)
{
if (NUMBER % i == 0)
{
if (!ifContains(dividors, i))
dividors.push_back(i);
int dividednumber = NUMBER / i;
if (!ifContains(dividors,dividednumber))
dividors.push_back(dividednumber);
}
}
#pragma omp single
sort(dividors.begin(), dividors.end());
#pragma omp single
for (int i = 0; i < dividors.size(); i++)
{
cout << dividors[i] << "\r\n";
}
}
}

There are several ways to fix this. The simplest is just to use the ordered clause. See the code below. However, this removes some of the parallelism. A better way is to declare prviate dividors vectors (which I call dividors_private) inside the parallel block so that each thread get's it's own private version and then write to the dividors vector in critical block. The sorting is done on the private vectors in parallel. A final sort is done on dividors in a single thread but since most of it is already sorted it goes fast. See the second code below:
The version of the code with ordered:
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include "omp.h"
using namespace std;
vector<int> dividors;
int NUMBER = 1000;
bool ifContains(vector<int> dividors, int dividedNumber)
{
for(int i=0; i<dividors.size(); i++)
{
if(dividors[i] == dividedNumber)
return true;
}
return false;
}
void doStuff()
{
int sqr = (int) sqrt(NUMBER);
int sqrp1 = sqr + 1;
#pragma omp parallel
{
#pragma omp for ordered
for (int i = 1; i < sqrp1; i++)
{
if (NUMBER % i == 0)
{
#pragma omp ordered
{
dividors.push_back(i);
if (!ifContains(dividors, i))
dividors.push_back(i);
int dividednumber = NUMBER / i;
if (!ifContains(dividors, dividednumber))
dividors.push_back(dividednumber);
}
}
}
}
sort(dividors.begin(), dividors.end());
for (int i = 0; i < dividors.size(); i++)
{
cout << dividors[i] << "\r\n";
}
}
int main()
{
doStuff();
return 0;
}
The version of the code which uses private dividors vectors
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include "omp.h"
using namespace std;
vector<int> dividors;
int NUMBER = 1000;
bool ifContains(vector<int> dividors, int dividedNumber)
{
for(int i=0; i<dividors.size(); i++)
{
if(dividors[i] == dividedNumber)
return true;
}
return false;
}
void doStuff()
{
int sqr = (int) sqrt(NUMBER);
int sqrp1 = sqr + 1;
#pragma omp parallel
{
vector<int> dividors_private;
#pragma omp for nowait
for (int i = 1; i < sqrp1; i++)
{
if (NUMBER % i == 0)
{
dividors_private.push_back(i);
//printf("i %d\n", i);
if (!ifContains(dividors_private, i))
dividors_private.push_back(i);
int dividednumber = NUMBER / i;
if (!ifContains(dividors_private, dividednumber))
dividors_private.push_back(dividednumber);
}
}
sort(dividors_private.begin(), dividors_private.end());
#pragma omp critical
{
dividors.insert(dividors.end(), dividors_private.begin(), dividors_private.end());
}
}
sort(dividors.begin(), dividors.end());
for (int i = 0; i < dividors.size(); i++)
{
cout << dividors[i] << "\r\n";
}
}
int main()
{
doStuff();
return 0;
}

I ran your code in gdb and am getting random crashed on the calls to dividors.push_back(...). This seem to be a race condition and the reason is that you are changing the dividors vector from several threads at once and in this sense the std::vector class is not thread safe. See std::vector, thread-safety, multi-threading.
What you have to do is to make sure that no thread changes the vector while another thread changes or reads it. This goes for sorting it on every thread to. Do it in a #pragma omp single, it only needs to be sorted once and especially not from several threads at once.

Related

How to make a function that can only be executed on one thread simultaneously?

I have a program that i am using to find prime numbers. it is executing on multiple threads. I am using the GetNextNumber() function for the threads to call to get a number to check if it is prime, however it seems that this function is being executed simultaneously by more than 1 thread, so sometimes two threads get the same number. here is my code:
#include "pch.h"
#include <cmath>
#include <fstream>
#include <thread>
#include <iostream>
#include <string>
int nextInt = 1;
std::ofstream file;
bool TestPrime(int number)
{
double rootInt = sqrt(number);
for (int i = 3; i <= rootInt; i += 2)
{
double divValue = (double)number / i;
if (int(divValue) == divValue)
{
return false;
}
}
return true;
}
int GetNextNumber()
{
return (nextInt += 2);
}
void PrimeFinderThread()
{
while (true)
{
int number = GetNextNumber();
bool isPrime = TestPrime(number);
if (isPrime)
{
std::string fileOutput = std::to_string(number) + "-";
file << fileOutput;
}
}
}
int main() {
file.open("primes.txt", std::ofstream::app);
file << 2 << "-";
std::thread threads[4];
for (int i = 0; i < 4; i++) {
threads[i] = std::thread(PrimeFinderThread);
}
for (int i = 0; i < 4; i++) {
threads[i].join();
}
return 0;
}
Using a mutex is a valid solution, but in this case it causes unnecessary overhead. You can simply make nextId atomic:
std::atomic<int> nextId{1};
This makes the increment operation in GetNextNumber atomic, so no two threads will get the same value.
Use a std::mutex with std::lock_guard. It will prevent simultaneous execution of the function.
#include "pch.h"
#include <cmath>
#include <fstream>
#include <thread>
#include <iostream>
#include <string>
#include <mutex>
int nextInt = 1;
std::ofstream file;
bool TestPrime(int number)
{
double rootInt = sqrt(number);
for (int i = 3; i <= rootInt; i += 2)
{
double divValue = (double)number / i;
if (int(divValue) == divValue)
{
return false;
}
}
return true;
}
int GetNextNumber()
{
static std::mutex m;
const std::lock_guard<std::mutex> lock(m);
return (nextInt += 2);
}
void PrimeFinderThread()
{
while (true)
{
int number = GetNextNumber();
bool isPrime = TestPrime(number);
if (isPrime)
{
std::string fileOutput = std::to_string(number) + "-";
file << fileOutput;
}
}
}
int main() {
file.open("primes.txt", std::ofstream::app);
file << 2 << "-";
std::thread threads[4];
for (int i = 0; i < 4; i++) {
threads[i] = std::thread(PrimeFinderThread);
}
for (int i = 0; i < 4; i++) {
threads[i].join();
}
return 0;
}

Bad Access on Sieve

My block of code runs, but whenever I type in input, it returns Thread 1: EXC_BAD_ACCESS (code=1, address=0x4). I'm fairly new to coding, and was wondering what's wrong.
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int x, count = 1;
cin >> x;
vector<int> sieve;
fill(sieve.begin(), sieve.begin()+x-1, 1);
while (count <= x) {
for (int i = count+1; i <= x; i++) {
if (sieve[i-1] == 1) {
count = i;
break;
}
}
for (int i = count*count; i < x; i+=count) {
sieve[i-1] = 0;
}
}
for (int i = 0; i < x-1; i++) {
if (sieve[i] == 1) {
cout << i+1 << endl;
}
}
}
You need to allocate space for your sieve. So you might want vector<int> sieve(x). Or, you can even do vector<int> sieve(x, 1), which will allocate space for x ints and fill them all with 1s already, so you won't need the fill afterwards.

main.exe has stopped working in code blocks

This is a code I wrote for bubble sort. I gave a comment //this line due to which I'm unable to run this program. Every time the first element of the array needs to be stored in 'temp'.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int arr[7]={7,8,5,2,4,6};
int temp;
for(int i=0;i<7;i++)
{
temp=arr[0]; //this line.
for(int j=0;j<7-i;j++)
{
if(temp<arr[j])
temp=arr[j];
else
swap(arr[j],arr[j-i]);
}
}
for(int k=0;k<7;k++)
{
cout<<arr[k]<<endl;
}
return 0;
}
There were some issue with your program:
Array size should be 6 instead of 7
The for loop condition was incorrect
swap(arr[j],arr[j-i]) will break when j-i is less than 0(for instance i=1, j=0).
Program
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int arr[6]={7,8,5,2,4,6};
for(int i=0;i<5;i++)
{
for(int j=0;j<5-i;j++)
{
if(arr[j]>arr[j+1])
swap(arr[j],arr[j+1]);
}
}
for(int k=0;k<6;k++)
cout<<arr[k]<<endl;
return 0;
}
Ideone
You seem flipped for() loops over... what I got - not the most elegant solution, but I stick to the same tools you're using. Mostly. I could make it as template and it would work with any appropriate container. std::sort sometimes implemented like that.
#include <iostream>
#include <algorithm>
void bubbleSort(int arr[], int n)
{
bool swapped;
for (int i = 0; i < n-1; i++)
{
swapped = false;
for (int j = 0; j < n-i-1; j++)
{
if (arr[j] > arr[j+1])
{
std::swap(arr[j], arr[j+1]);
swapped = true;
}
}
// no elements were swapped, array already sorted.
if (!swapped) break;
}
}
int main()
{
int arr[] = {7,8,5,2,4,6};
bubbleSort(arr, std::size(arr));
for( auto v : arr )
std::cout << v << " ";
std::cout << std::endl;
}
In C++11 and later <algorithm> can be replaced by <utility>, it's just for swap/size.

OpenMP C++ program with Vectors

I wrote a OpenMP program in C++ which basically finds the suffix-prefix overlap of a given length. All my strings are stored in a vector and I have two for loops for checking the overlap (all against all). I am trying to make the for loop parallel, but it does not improve the time. Following is my program
vector<string> Reads; // contains all strings
vector<int> *AdjList = new vector<int>[Reads.size()];
vector<int> *OLL = new vector<int>[Reads.size()];
// int i,j;
/*# pragma omp parallel \
shared ( AdjList, OLL ) \
private ( i, j )*/
#pragma omp parallel for
for(int i=0; i<Reads.size(); i++){
string suff = Reads.at(i).substr(Reads.at(i).length() - minOLL, minOLL);
for(int j=0; j<Reads.size(); j++){
if(i != j){
size_t found = rabin_karp(suff, Reads.at(j));
if(found != -1){
string pref1 = Reads.at(j).substr(0, found);
string suff1 = Reads.at(i).substr(Reads.at(i).length() - minOLL - found, found);
if(pref1.compare(suff1) == 0){
AdjList[i].push_back(j);
OLL[i].push_back(found + minOLL);
}
}
}
}
}
I guess reduction might help, but I am clueless about how to use it
1.since size of strings may be different you may use schedule(dynamic) so the tasks dynamically assigned to threads. 2. you can split inner loop into two loops to get rid of if statement. 3. substr is not a good choice because leads to creation of new string so you may use and save character positions to speed the code. However below applied 1, 2 mentioned cases:
#pragma omp parallel for schedule(dynamic)
for(int i=0; i<Reads.size(); i++){
string suff = Reads.at(i).substr(Reads.at(i).length() - minOLL, minOLL);
for(int j=0; j< i; j++){
size_t found = rabin_karp(suff, Reads.at(j));
if(found != -1){
string pref1 = Reads.at(j).substr(0, found);
string suff1 = Reads.at(i).substr(Reads.at(i).length() - minOLL - found, found);
if(pref1.compare(suff1) == 0){
AdjList[i].push_back(j);
OLL[i].push_back(found + minOLL);
}
}
}
for(int j=i+1; j< Reads.size(); j++){
size_t found = rabin_karp(suff, Reads.at(j));
if(found != -1){
string pref1 = Reads.at(j).substr(0, found);
string suff1 = Reads.at(i).substr(Reads.at(i).length() - minOLL - found, found);
if(pref1.compare(suff1) == 0){
AdjList[i].push_back(j);
OLL[i].push_back(found + minOLL);
}
}
}
}
Here's an example.
#include "pch.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <omp.h>
using namespace std;
class Monitorius {
private:
int M[50];
int count = 0;
int suma = 0;
public:
Monitorius()
{
for (int i = 0; i < 50; i++)
M[i] = 0; // nusinulinamas masyvas
}
// Funkcijos ---------------------------------------
void Prideti(int skaicius)
{
#pragma omp critical
{
M[count] = skaicius;
count++;
Suma();
}
}
void Suma()
{
suma = 0;
for (int i = 0; i < 50; i++) {
suma += M[i];
}
cout << "Suma: " << suma << endl;
}
};
void paleistiGijas(Monitorius *monitorius) {
#pragma omp parallel num_threads(5)
{
for (int i = 1; i <= 10; i++) {
monitorius->Prideti(i);
}
}
}
int main()
{
// Monitoriaus sukurimas bei giju paleidimas
Monitorius *monitorius = new Monitorius();
// Pradedamas giju darbas
paleistiGijas(monitorius);
// Atlaisvinama atmintis
delete(monitorius);
return 0;
}

Run-Time Check Failure #2 - Stack around the variable 'A' was corrupted. Solution needed

I started to learn C++ and encounter a error.
I just create a class that produce a 10x10 matrix, put integers 0 to 99 into the matrix and print them out. However, it pop out a stack error with one of the value that supposed to be 93 become 0. I have no clue about it. Thank you for your answer.
//myclass.h
#pragma once
class Matrix {
private:
int _2dmatrix [10][10];
public:
Matrix ();
~Matrix ();
void printMatrix ();
};
// myclass.cpp
#include "myclass.h"
#include <iostream>
using namespace std;
Matrix::Matrix () {
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++) {
_2dmatrix[i+1][j+1] =i*10+j;
}
}
Matrix::~Matrix () {}
void Matrix::printMatrix () {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
cout << _2dmatrix[i+1][j+1] << "\t";
}
cout << "\n";
}
}
//source.cpp
#include <iostream>
#include "myclass.h"
using namespace std;
int main() {
Matrix A;
A.printMatrix();
return 0;
}
Arrays in C++ are zero-based. Simply change i+1to i and j+1 to j.