I am trying to write a parallel bubblesort function. I am running into an error when using boost::bind:
void swap(vector<int>& input, int i, int j)
{
if (input[i] > input[j])
{
int temp = input[j];
input[j] = input[i];
input[i] = temp;
}
return;
}
void parallel_bubblesort(vector<int>& input, int, int)
{
int i, j, temp;
for (i = 0; i < input.size(); i++)
{
boost::asio::io_service ioService;
boost::thread_group threadpool;
for (j = 0; j < input.size() - 1; j++)
{
ioService.post(boost::bind(&swap, boost::ref(input), 2 * j + i % 2, 2 * j + 1 + i % 2));
}
for (int t = 0; t < NUM_THREADS; t++)
{
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
}
threadpool.join_all();
ioService.stop();
}
return;
}
It snags on the line
ioService.post(boost::bind(&swap, boost::ref(input), 2 * j + i % 2, 2 * j + 1 + i % 2));
The error says
no matching function for call to ‘bind(<unresolved overloaded function type>, std::vector<int, std::allocator<int> >&, int, int)’
This seems weird, because none of these are overloaded at all, does anybody know what this means?
Edit: Here is the full program
#include <iostream>
#include <chrono>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <algorithm>
#include <boost/thread.hpp>
#include <boost/asio/io_service.hpp>
#define NUM_THREADS 4
using namespace std;
using namespace boost;
using namespace boost::this_thread;
int check_solution(const vector<int>&);
void bubblesort(vector<int>&);
void swap1(vector<int>&, int, int);
void parallel_bubblesort(vector<int>&);
int main()
{
string line, token;
string file = "test.txt";
vector<int> unsorted_integers;
//print out filename
cout << file << endl;
ifstream myfile(file);
//open file
if(myfile.is_open())
{
//load everything into a vector
while (getline(myfile, line))
{
int temp;
std::istringstream ss(line);
std::getline(ss, token, '\n');
temp = atoi(token.c_str());
unsorted_integers.push_back(temp);
}
}
vector<int> unsorted_integers2(unsorted_integers);
//starts clock
std::chrono::high_resolution_clock::time_point start2 = std::chrono::high_resolution_clock::now();
//run the sort function and check for correctness
parallel_bubblesort(unsorted_integers2);
if(check_solution(unsorted_integers2))
{
cout << "The parallel sort solution is correct" << endl;
}
else
{
cout << "The parallel sort solution is incorrect" << endl;
}
//stops clock and prints times
std::chrono::high_resolution_clock::time_point end2 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> total_time2 = std::chrono::duration_cast<std::chrono::duration<double>>(end2 - start2);
cout << "The parallel sort function took " << total_time2.count() << " seconds." << endl;
return 0;
}
void swap1(vector<int>& input, int i, int j)
{
if (input[i] > input[j])
{
int temp = input[j];
input[j] = input[i];
input[i] = temp;
}
return;
}
void parallel_bubblesort(vector<int>& input, int, int)
{
int i, j;
for (i = 0; i < input.size(); i++)
{
boost::asio::io_service ioService;
boost::thread_group threadpool;
for (j = 0; j < input.size() - 1; j++)
{
ioService.post(boost::bind(&swap1, boost::ref(input), 2 * j + i % 2, 2 * j + 1 + i % 2));
}
for (int t = 0; t < NUM_THREADS; t++)
{
threadpool.create_thread(boost::bind(&boost::asio::io_service::run, &ioService));
}
threadpool.join_all();
ioService.stop();
}
return;
}
int check_solution(const vector<int>& solution)
{
vector<int> correct_solution(solution);
std::sort(correct_solution.begin(), correct_solution.end());
return (solution == correct_solution);
}
You are probably doing using namespace std; somewhere, and std::swap is a thing. I suggest you simply rename your swap function to something else.
Related
This question is not about where to put the srand function.
I have just started learning DSA with Insertion Sort. I have written a C++ program to perform Insertion Sort and wanted to create some neat visuals of the Time Analysis. I tried generating Random Arrays for the Time Analysis using the rand() function but the Arrays generated seem to have a character at the end. The elements in the character array should all be single digit integers like '0' '3' and so on.....
The Main Function of the Program:
#include <iostream>
#include <time.h>
#include <cstdlib>
#include <iomanip>
using namespace std;
int size(char a[]) {
int l = 0;
while (a[l] != NULL) {
l++;
}
return l;
}
void InsertionSort(char arr[]) {
for (int k = 1; k < size(arr); k++) {
char temp = arr[k];
int i = k - 1;
while (i >= 0 && arr[i] > temp) {
arr[i + 1] = arr[i];
i--;
}
arr[i + 1] = temp;
}
}
int main(void) {
//Generate Random Arrays of size snum
for (int k = 1; k < 100; k++) {
int snum = k * 100;
char Array[snum];
srand(time(NULL));
for (int s = 0; s < snum; s++)
{
int no = rand() % 9 + 1;
Array[s] = no + '0';
}
cout << "START\t";
//cout<<"\n"<<Array<<"END\n"; // Character is being Printed at the end........ :-(
clock_t start, end;
start = clock();
InsertionSort(Array);
end = clock();
double time_taken = double(end - start) / double(CLOCKS_PER_SEC);
cout << "\"" << fixed << time_taken << setprecision(9) << "\",\"" << 100 * k << "\"" << endl;
}
}
How I Compile and Run the Program:
g++ InsertionSort.cpp
./a.out > InsertionSort.txt
--------------EDIT--------------
Based on the suggestions, I have replaced the Array with a vector. Please provide any further suggestions....
RandomIntVector.cpp
#include "RandomIntVector.h"
#include <random>
#include <vector>
using namespace std;
vector<int> RandomVector(int size){
uniform_int_distribution<> d(1, 1000);
mt19937 gen;
vector<int> Ar;
for(int s=0; s<(size-1); s++)
{
int no = d(gen);
Ar.push_back(no);
}
return Ar;}
InsertionSort.cpp
#include "InsertionSort.h"
#include <vector>
using namespace std;
void InsertionSort(vector<int> arr){
int size=arr.size();
for(int k=1;k<size;k++){
int temp = arr[k];
int i=k-1;
while(i>=0 && arr[i]>temp ){
arr[i+1]=arr[i];
i--;
}
arr[i+1]=temp;
}
}
Main.cpp
#include <iostream>
#include <vector>
#include <chrono>
#include <iomanip>
#include "RandomIntVector.h"
#include "InsertionSort.h"
using namespace std;
int main(void){
//Generate Random Arrays of size snum
for(int k=1;k<100;k++){
vector<int> Array = RandomVector(100*k);
clock_t start, end;
start = clock();
InsertionSort(Array);
end = clock();
double time_taken = double(end - start) /
double(CLOCKS_PER_SEC);
//Print the Time Taken along with the size of the Input
cout<<"\""<<fixed << time_taken << setprecision(9)<<"\",\""
<<100*k<<"\""<<endl;
}
return 0;
}
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;
}
I wanted to learn how threads work, and I tried to make a program, which would use 2 threads, to copy a picture (just to test my newly acquired threading skills) . But I bumped into an error, probably because my interval (created by the interval function) is only working ( I believe) with one dimensional arrays.How can I change my program , to correctly create intervals , which work on 2 dimensional arrays, such as pictures ?
#include <iostream>
#include <vector>
#include <time.h>
#include <thread>
#include <mutex>
#include <png++/png.hpp>
std::mutex my_mutex;
std::vector<int> interval(int max, int n_threads)
{
std::vector<int> intervallum;
int ugras = max / n_threads;
int maradek = max % n_threads;
int n1 = 0;
int n2;
intervallum.push_back(n1);
for (int i = 0; i < n_threads; i++)
{
n2 = n1 + ugras;
if (i == n_threads - 1)
n2 += maradek;
intervallum.push_back(n2);
n1 = n2;
}
return intervallum;
}
void create_image(png::image<png::rgb_pixel> image, png::image<png::rgb_pixel> new_image, int start, int end)
{
std::lock_guard<std::mutex> lock(my_mutex);
for (int i = start; i < end; i++)
for (int j = start; j < end; j++)
{
new_image[i][j].red = image[i][j].red;
new_image[i][j].blue = image[i][j].blue;
new_image[i][j].green = image[i][j].green;
}
}
int main()
{
png::image<png::rgb_pixel> png_image("mandel.png");
int image_size = png_image.get_width() * png_image.get_height();
png::image<png::rgb_pixel> new_image(png_image.get_width(), png_image.get_height());
time_t start, end;
time(&start);
int size = 2;
std::vector<std::thread> threads;
std::vector<int> stuff_interval = interval(image_size, size);
for (int i = 0; i < size-1; i++)
threads.push_back(std::thread(create_image, std::ref(png_image), std::ref(new_image), stuff_interval[i], stuff_interval[i + 1]));
for (auto& i : threads)
i.join();
create_image(png_image,new_image,stuff_interval[size-2],stuff_interval[size-1]);
new_image.write("test.png");
time(&end);
std::cout << (start - end) << std::endl;
return 0;
}
Okay , I found a way around it (this way I am not getting segmentation error, but it does not copy the image correctly, the new image is fully black, here is the code :
EDIT : seems like, I was passing wrong the pictures, that is the reason why the picture was black.
#include <iostream>
#include <vector>
#include <time.h>
#include <thread>
#include <mutex>
#include <png++/png.hpp>
std::mutex my_mutex;
std::vector<int> interval(int max, int n_threads)
{
std::vector<int> intervallum;
int ugras = max / n_threads;
int maradek = max % n_threads;
int n1 = 0;
int n2;
intervallum.push_back(n1);
for (int i = 0; i < n_threads; i++)
{
n2 = n1 + ugras;
if (i == n_threads - 1)
n2 += maradek;
intervallum.push_back(n2);
n1 = n2;
}
return intervallum;
}
void create_image(png::image<png::rgb_pixel>& image, png::image<png::rgb_pixel>& new_image, int start, int end)
{
std::lock_guard<std::mutex> lock(my_mutex);
for (int i = start; i < end; i++)
for (int j = 0; j < image.get_height(); j++)
{
new_image[i][j].red = image[i][j].red;
new_image[i][j].blue = image[i][j].blue;
new_image[i][j].green = image[i][j].green;
}
}
int main()
{
png::image<png::rgb_pixel> png_image("mandel.png");
int image_size = png_image.get_width() * png_image.get_height();
png::image<png::rgb_pixel> new_image(png_image.get_width(), png_image.get_height());
time_t start, end;
time(&start);
int size = 2;
std::vector<std::thread> threads;
std::vector<int> stuff_interval = interval(png_image.get_width(), size);
new_image.write("test2.png");
for (int i = 0; i < size - 1; i++)
threads.push_back(std::thread(create_image, std::ref(png_image), std::ref(new_image), stuff_interval[i], stuff_interval[i + 1]));
for (auto &i : threads)
i.join();
create_image(std::ref(png_image), std::ref(new_image), stuff_interval[size - 1], stuff_interval[size]);
new_image.write("test.png");
time(&end);
std::cout << (start - end) << std::endl;
return 0;
}
In my Intro to Computer Science class I am beginning to learn the basics of sorting algorithms. So far, we have gone over Bubble, Selection, and Insertion Sort.
After class today, the instructor has requested us to "enhance" the program by adding code to print out the vector/array after every swap during the sorting. I am at a complete loss as to how I would make this happen. I'm thinking something like :
if (swapped) { cout << vec << " "; }
but without even trying, I'm certain this wouldn't work. Any help is very much appreciated. Here's my code so far:
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
vector<int> createVec(int n) {
unsigned seed = time(0);
srand(seed);
vector<int> vec;
for (int i = 1; i <= n; ++i) {
vec.push_back(rand() % 100 + 1);
}
return vec;
}
void showVec(vector<int> vec) {
for (int n : vec) {
cout << n << " ";
}
}
void bubbleSort(vector<int> &vec) {
int n = vec.size();
bool swapped = true;
while (swapped) {
swapped = false;
for (int i = 1; i <= n-1; ++i) {
if (vec[i-1] > vec[i]) {
swap(vec[i-1], vec[i]);
swapped = true;
}
}
}
}
void selectionSort(vector<int> &vec) {
int n = vec.size();
int maxIndex;
for (int i = 0; i <= n-2; ++i) {
maxIndex = i;
for (int j = i+1; j <= n-1; ++j) {
if (vec[j] < vec[maxIndex]) {
maxIndex = j;
}
}
swap(vec[i], vec[maxIndex]);
}
}
int main()
{
vector<int> numbers = createVec(20);
showVec(numbers);
cout << endl;
//bubbleSort(numbers);
selectionSort(numbers);
showVec(numbers);
return 0;
}
For example in the called function selectionSort substitute this statement
swap(vec[i], vec[maxIndex]);
for the following statement
if ( i != maxIndex )
{
swap(vec[i], vec[maxIndex]);
showVec( vec );
cout << endl;
}
Also the function showVec should declare the parameter as having a constant referenced type
void showVec( const vector<int> &vec) {
for (int n : vec) {
cout << n << " ";
}
}
I keep getting the segmentation fault (core dumped) on the code below. Any ideas on why this is happening. The code is designed to read numbers from a text document, convert them to integers, perform radix sort, and print out the array.
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <time.h>
#include <sstream>
using namespace std;
int getMax(int arr[], int n)
{
int max = arr[0];
for (int i = 1; i < n; i++)
if (arr[i] > max)
max = arr[i];
return max;
}
void countSort(int arr[], int n, int exp)
{
int output[n];
int i, count[10] = {0};
for (i = 0; i < n; i++)
count[(arr[i] / exp) % 10]++;
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
for (i = n - 1; i >= 0; i--)
{
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
for (i = 0; i < n; i++)
arr[i] = output[i];
}
void radixsort(int arr[], int n)
{
clock_t clockStart;
clockStart = clock();
int m = getMax(arr, n);
for (int exp = 1; m / exp > 0; exp *= 10)
countSort(arr, n, exp);
cout << "\nTime taken by radix sort: " << (double)(clock() - clockStart) / CLOCKS_PER_SEC << endl;
}
int StrToInt(string sti)
{
int f;
stringstream ss(sti); //turn the string into a stream
ss >> f;
return f;
}
int main()
{
int arr[10000];
int i = 0;
int result;
string line = "";
ifstream myfile;
myfile.open("integers2.txt");
if(myfile.is_open())
{
while(!myfile.eof())
{
getline(myfile, line);
result = StrToInt(line);
arr[i] = result;
//cout<< arr[i] <<"\n";
i++;
}
}
int n = sizeof(arr)/sizeof(arr[0]);
radixsort(arr, n);
for (int i = 0; i < n; i++)
{
cout << arr[i] << "\n";
}
return 0;
}
Contents of the text file I am using for input:
1244
3455
6565
55
765
8768
687
879
Your program has undefined behavior, because it uses more entries of the array than you initialized with data. You pass the length of the entire array for n even though only a small portion of it, from 0 to i, has been initialized.
Change the code to use n in place of i in the reading loop, and pass that n unmodified to the sort function. This is going to fix the problem (demo).
int n = 0;
myfile.open("integers2.txt");
if(myfile.is_open()) {
while (myfile >> arr[n]) {
n++;
}
}
radixsort(arr, n);
Here's your working code:
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <time.h>
#include <sstream>
using namespace std;
int getMax(int arr[], int n)
{
int max = arr[0];
for (int i = 1; i < n; i++)
if (arr[i] > max)
max = arr[i];
return max;
}
void countSort(int arr[], int n, int exp)
{
int output[n];
int i, count[10] = {0};
for (i = 0; i < n; i++)
count[(arr[i] / exp) % 10]++;
for (i = 1; i < 10; i++)
count[i] += count[i - 1];
for (i = n - 1; i >= 0; i--)
{
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
for (i = 0; i < n; i++)
arr[i] = output[i];
}
void radixsort(int arr[], int n)
{
clock_t clockStart;
clockStart = clock();
int m = getMax(arr, n);
for (int exp = 1; m / exp > 0; exp *= 10)
countSort(arr, n, exp);
cout << "\nTime taken by radix sort: " << (double)(clock() - clockStart) / CLOCKS_PER_SEC << endl;
}
int StrToInt(string sti)
{
int f;
stringstream ss(sti); //turn the string into a stream
ss >> f;
return f;
}
int main()
{
const int MAX_SIZE = 10;
int arr[ MAX_SIZE ] = { 0 };
//int i = 0;
//int result = 0;
string line = "";
ifstream myfile;
myfile.open("integers2.txt");
if(!myfile.is_open())
{
cerr << "Could not open file!\n";
return -1;
}
cout << "Reading integers...\n";
int index = 0;
//while ( index < SIZE && getline( myfile, line ) )
while ( index < MAX_SIZE && myfile >> arr[ index ] )
{
//getline( myfile, line );
//result = StrToInt( line );
//arr[index] = std::stoi( line );
cout << arr[index] <<"\n";
index++;
}
cout << "Sorting integers...\n";
//int n = sizeof(arr) / sizeof(arr[0]);
radixsort( arr, index );
for ( int i = 0; i < index; i++ )
{
cout << arr[i] << "\n";
}
return 0;
}
Some points:
Check std::stoi for string to integer conversion; BTW, you don't need to do that. Just read it directly like this: while ( file >> integer ).
Need to check if the file is open; return ERROR otherwise; in your case, the rest of the code was executing anyway even if the file was not open i.e. code after if ( myfile.open() ) { ... }
while( !myfile.eof() ) is bad practice. See: Why is iostream::eof inside a loop condition considered wrong?
You don't need to calculate the size like int n = sizeof(arr) / sizeof(arr[0]); because you already know the size. Just use a const for this.
While reading from file, you also need to validate the maximum size of your array. You should read what the size allows you. Take care of out-of-bounds read / write errors.
Use <ctime> instead of <time.h>.