I'm trying to do a sum of 2 matrices using pthreads in c++. I'm stuck at trying to pass the result of the sum calculated inside a thread to my main function.
The 2 values to be added are inside a struct:
struct sum{
int value1;
int value2;
int result;
}typedef struct_sum;
And the struct containing the values is passed as an argument to pthread_create() so that the operation is excuted inside a thread.
Here's my routine:
void * routine(void * sum) {
std::cout<<((struct_sum *)sum)->value1 + ((struct_sum *)sum)->value2<<std::endl;
std::cout<<((struct_sum *)sum)->value1<<std::endl;
std::cout<<((struct_sum *)sum)->value2<<std::endl;
int i = (((struct_sum *) sum)->value1 + ((struct_sum *) sum)->value2);
// memcpy(&(((struct_sum *)sum)->result), reinterpret_cast<const void *>(i), sizeof(i));
((struct_sum *)sum)->result = i;
std::cout<<&(((struct_sum *)sum)->result)<<std::endl;
pthread_exit(nullptr);
}
In the first 3 cout I check if my values are coming correctly to the thread.
In the last cout (before exiting the thread) I check the memory address of the result element of the struct (so I can see that it has the same address inside the main function).
Here's the main function:
int main(int argc, char * argv[]) {
int mat_1[ROW_SIZE][COLUMN_SIZE] = {{1, 2},
{6, 7}};
int mat_2[ROW_SIZE][COLUMN_SIZE] = {{3, 15},
{9, 14}};
int mat_result[ROW_SIZE][COLUMN_SIZE];
int mat_size = sizeof(mat_1) / sizeof(int);
int row_size = sizeof(mat_1) / sizeof(mat_1[0]);
int column_size = sizeof(mat_1[0]) / sizeof(int);
pthread_t threads[mat_size];
int thread_number = 0;
int thread_handler;
for (int row = 0; row < row_size; row++) {
for (int column = 0; column < column_size; column++) {
struct_sum *result;
result = static_cast<struct_sum *>(malloc(sizeof(struct_sum)));
result->value1 = mat_1[row][column];
result->value2 = mat_2[row][column];
result->result = 0;
thread_handler = pthread_create(&threads[thread_number], nullptr, routine, result);
if(thread_handler) return(-1);
std::cout << &(result->result)<<std::endl;
thread_number++;
mat_result[row][column] = result->result;
// free(result);
}
}
pthread_exit(nullptr);
}
I'm having two problems:
Even though the result has the same address in the main and in the thread, when I copy the value of i to ((struct_sum *)sum)->result, in the main function, result->result is still 0.
When I uncomment the memcpy() line the thread simply don't run, so I don't know how I'm doing it wrong.
I was expecting that in my main function the statement std::cout << (result->result) <<std::endl would return me the result of the operation, but the current value is 0.
So, how do I perform the memcpy() correctly in the thread?
You have to JOIN your threads. It means, wait them to finish.
The way you were doing is basically starting the thread and not giving it a guaranteed time do to anything. Besides that, some important change to the API, check the comments below:
void * routine(void * sum) {
int i = (((struct_sum *) sum)->value1 + ((struct_sum *) sum)->value2);
((struct_sum *)sum)->result = i;
// notice you don't need memcpy(), in fact...
// but you could use it here if you want... it won't fail.
// you have to use this function so it return your result to the main thread.
pthread_exit(sum);
}
int main(int argc, char * argv[]) {
int mat_1[ROW_SIZE][COLUMN_SIZE] = {{1, 2},
{6, 7}};
int mat_2[ROW_SIZE][COLUMN_SIZE] = {{3, 15},
{9, 14}};
int mat_result[ROW_SIZE][COLUMN_SIZE];
int mat_size = sizeof(mat_1) / sizeof(int);
int row_size = sizeof(mat_1) / sizeof(mat_1[0]);
int column_size = sizeof(mat_1[0]) / sizeof(int);
pthread_t threads[mat_size];
int thread_number = 0;
int thread_handler;
for (int row = 0; row < row_size; row++) {
for (int column = 0; column < column_size; column++) {
struct_sum *result;
result = static_cast<struct_sum *>(malloc(sizeof(struct_sum)));
result->value1 = mat_1[row][column];
result->value2 = mat_2[row][column];
result->result = 0;
thread_handler = pthread_create(&threads[thread_number], nullptr, routine, result);
if(thread_handler) return(-1);
// std::cout << &(result->result)<<std::endl;
thread_number++;
// forget this line below
// mat_result[row][column] = result->result;
}
}
// here you wait for the threads to JOIN
// here it means they actually "finished" their job
for (int i = 0; i < mat_size; i++)
{
struct_sum *result;
// here you wait for the threads to finish their job
// add something to your struct to "identify" the thread, so
// you can figure out where in the final matrix you put the result
pthread_join(threads[i], (void**)&result);
std::cout << result->result << "\n";
// this will print the correct sums: 4, 17, 15 and 21
// notice: it will be printed in ANY order, once you
// don't know which thread will finish first
// but result->result has the... result you need!
// you have to figure out how to fit this result in your matrix.
// but this is out of scope of the question
// and you can do yourself. have fun! :-)
// here you can free the result, you already got the value!
free(result);
}
// you don't need this line below... this goes to routine()
// pthread_exit(nullptr);
return 0;
}
Related
I wanted to write a function which upon being called deletes an element from an array given that the parameters passed in the deleteArray function were the array, its length and the value of the element to be deleted.
Tried breaking out of the for loop while transversing through the array if the element was found and then tried using i's value in another for loop to replace the current elements with their next element.
like array[j] = array[j + 1]
Here is the code:
#include <iostream>
using namespace std;
void deleteElement(int[], int, int);
int main() {
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i];
}
return 0;
}
void deleteElement(int array2[], int length, int element) {
int i = 0;
for (int i; i < length; i++) {
if (array2[i] == element) {
for (int j = i; j < length; j++) {
array2[j] = array2[j + 1];
}
break;
}
}
if (i == (length - 1)) {
cout << ("Element doesn't exist\n");
}
cout << "Testing OP in deleteElement\n";
for (int i = 0; i < length; i++) {
cout << array2[i];
}
}
Expected:
Testing OP in deleteElement
14356
In main function
1356
Actual:
Testing OP in deleteElement
14356
In main function
14356
The problem is rather silly:
At the beginning of deleteElement(), you define i with int i = 0;, but you redefine another variable i as a local index in each for loop. The for loop introduces a new scope, so the int i definition in the first clause of the for loop defines a new i, that shadows the variable with the same name defined in an outer scope.
for (int i; i < length; i++) {
And you do not initialize this new i variable.
There are 2 consequences:
undefined behavior in the first loop as i is uninitialized. The comparison i < length might fail right away.
the test if (i == (length - 1)) { tests the outer i variable, not the one that for iterated on. Furthermore, the test should be if (i == length) {
There are other issues:
the nested for loop iterates once too many times: when j == length - 1, accessing array[j + 1] has undefined behavior.
you do not update length, so the last element of the array is duplicated. You must pass length by reference so it is updated in the caller's scope.
Here is a corrected version:
#include <iostream>
using namespace std;
void deleteElement(int array2[], int& length, int element);
int main() {
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, &length, 4);
cout << "\nIn main function\n";
for (int i = 0; i < length; i++) {
cout << array1[i] << " ";
}
return 0;
}
void deleteElement(int array2[], int& length, int element) {
int i;
for (i = 0; i < length; i++) {
if (array2[i] == element)
break;
}
if (i == length) {
cout << "Element doesn't exist\n";
} else {
length -= 1;
for (; i < length; i++) {
array2[i] = array2[i + 1];
}
}
cout << "Testing OP in deleteElement\n";
for (i = 0; i < length; i++) {
cout << array2[i] << " ";
}
}
If you use the algorithm function std::remove, you can accomplish this in one or two lines of code without writing any loops whatsoever.
#include <algorithm>
#include <iostream>
void deleteElement(int array2[], int& length, int element)
{
int *ptr = std::remove(array2, array2 + length, element);
length = std::distance(array2, ptr);
}
int main()
{
int array1[] = { 1, 4, 3, 5, 6 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
for (int i = 0; i < length; ++i)
std::cout << array1[i];
}
Output:
1356
Note that we could have written the deleteElement function in a single line:
void deleteElement(int array2[], int& length, int element)
{
length = std::distance(array2, std::remove(array2, array2 + length, element));
}
Basically, std::remove moves the removed element to the end of the sequence, and returns a pointer to the beginning of the removed elements.
Thus to get the distance from the beginning of the array to where the removed elements are located, usage of std::distance is done to give us our new length.
To remove only the first found element, std::find can be used, and then std::copy over the elements, essentially wiping out the item:
void deleteElement(int array2[], int& length, int element)
{
int *ptr = std::find(array2, array2 + length, element);
if ( ptr != array2 + length )
{
std::copy(ptr+1,array2 + length, ptr);
--length;
}
}
int main()
{
int array1[] = { 1, 4, 3, 5, 4, 6, 9 };
int length = sizeof(array1) / sizeof(array1[0]); //For length of array
deleteElement(array1, length, 4);
for (int i = 0; i < length; ++i)
std::cout << array1[i];
}
Output:
135469
There is no need for multiple loops in deleteElement. Additionally, your removal will fail to remove all elements (e.g. 4 in your example) if your array contains more than one 4, e.g.
int array1[] = { 1, 4, 3, 4, 5 };
You can simplify your deleteElement function and handle removing multiple occurrences of element simply by keeping a count of the number of times the element is found and by using your counter as a flag to control removal, e.g.:
void deleteElement(int array2[], int& length, int element)
{
int found = 0; /* flag indicating no. element found */
for (int i = 0; i < length; i++) { /* iterate over each element */
if (array2[i] == element) { /* check if matches current */
found += 1; /* increment number found */
continue; /* get next element */
}
if (found) /* if matching element found */
array2[i-found] = array2[i]; /* overwrite elements to end */
}
length -= found; /* update length based on no. found & removed */
}
Updating your example main() to show both pre-delete and post-delete, you could do something like the following:
int main (void) {
int array1[] = { 1, 4, 3, 4, 5 };
int length = sizeof array1 / sizeof *array1; //For length of array
cout << "\nBefore Delete\n";
for (int i = 0; i < length; i++)
cout << " " << array1[i];
cout << '\n';
deleteElement(array1, length, 4);
cout << "\nAfter Delete\n";
for (int i = 0; i < length; i++)
cout << " " << array1[i];
cout << '\n';
}
Example Use/Output
Which in the case where you array contains 1, 4, 3, 4, 5 would result in:
$ ./bin/array_del_elem
Before Delete
1 4 3 4 5
After Delete
1 3 5
While you are using an array of type int (of which there are many in both legacy and current code), for new code you should make use of the containers library (e.g. array or vector, etc...) which provide built in member functions to .erase() elements without you having to reinvent the wheel.
Look things over and let me know if you have further questions.
This is because the length of the array is never updated after deleting. Logically the length should decrease by 1 if the element was deleted.
To fix this, either
Pass the length by reference and decrease it by 1 if the element is actually deleted. OR
Return from the deleteElement some value which indicates that the element was deleted. And based of that, decrease the value of length in the main function.
Recalculating the array length will not help because the element is not actually deleted in memory. So the memory allocated to he array remains same.
Other issues:
The first for loop in deleteElement should run till j < length - 1.
The for loop creates a local variable i, which shadows the i variable in outer scope, so the outer i is never updated and always remains = 0
Im trying set an array to have always same value in first position, but idk how to do that. for example array[10] always array[0] = 100, then continue add ohters number like: array[100,1,2,3.....], loop array[100,1,2,3.....] etc.
int main() {
int arrayNumber[10];
while (true)
{
for (int i = 0; i < 10; i++)
{
arrayNumber[0] = 100;
printf("%d\n", arrayNumber[i]);
Sleep(100);
}
}
}
Set the first value outside the loop and start the loop at 1.
arrayNumber[0] = 100;
for (int i = 1; i < arraysize; i++)
{
arrayNumber[i] = i;
}
int main() {
int arrayNumber[10] = {100};
for (int i = 1; i < 10; i++) {
arrayNumber[i] = i;
}
}
The first operator above declares the array and initializes the first it's element with the value 100, then the loop fills other elements with 1, 2, 3, ..., 9.
Since your asked about C++ let introduce C++-like solution below.
#include <numeric>
int main() {
int arrayNumber[10] = {100};
std::iota(arrayNumber + 1, arrayNumber + 10, 1);
}
Here the function iota fills the passed range in the array with sequentially increasing values, starting with 1.
I'm currently trying to write a C++ program with pthreads.h for multi-threaded matrix multiplication.
I'm trying to create the threads as follows
int numthreads = (matrix[0].size() * rsize2);//Calculates # of threads needed
pthread_t *threads;
threads = (pthread_t*)malloc(numthreads * sizeof(pthread_t));//Allocates memory for threads
int rc;
for (int mult = 0; mult < numthreads; mult++)//rsize2
{
struct mult_args args;
args.row = mult;
args.col = mult;
cout << "Creating thread # " << mult;
cout << endl;
rc = pthread_create(&threads[mult], 0, multiply(&args), 0);
}
This then creates threads that execute my multiply function which is coded as follows
void *multiply(int x, int y)
{
int oldprod = 0, prod = 0, sum = 0;
cout << "multiply";
for(int i = 0; i < rsize2; i++)//For each row in #ofrows in matrix 2
{
prod = matrix[x][i] * matrix2[i][y];//calculates the product
sum = oldprod + prod; //Running sum starting at 0 + first product
oldprod = prod; //Updates old product
}
My error lies in my multiply function. I'm trying to find a compatible way to pass in an x and y coordinate for each thread so it knows specifically which summation to calculate but i'm not sure how to do this in a way that is acceptable for the pthreads_create() function.
Update:
I know that I have to use a struct to accomplish this
struct mult_args {
int row;
int col;
};
but I can't get the multiply function to accept the struct
You will have to modify your multiply function so that it takes a single void* parameter. To do this, you will need to make a struct to store x and y and pass a pointer to it in pthread_create.
struct multiply_params
{
int x;
int y;
multiply_params(int x_arg, int y_arg) noexcept :
x(x_arg), y(y_arg)
{}
};
// ...
for (int mult = 0; mult < numthreads; mult++)
{
cout << "Creating thread # " << mult;
cout << endl;
multiply_params* params = new multiply_params(1, 0);
rc = pthread_create(&threads[mult], 0, multiply, (void*) params);
}
Then in your multiply function, rewrite it like this, taking a single void* parameter which will be the pointer of multiply_params which we passed into pthread_create. You have to cast this argument from void* so we can access its fields.
void* multiply(void* arg)
{
multiply_params* params = (multiply_params*) arg;
int x = params->x;
int y = params->y;
delete params; // avoid memory leak
// ...
}
With the help of SO members, the following program successfully converts a static 1D array into a 2D vector by considering below criteria:
Each time an element with value = 0 is encountered, a new row is created. Basically when a 0 is encountered, row value is increased and column value is reset to 0. If a non-zero value is encountered, the row value is maintained and column value is increased.
// declarations
int givenArray[9] = {1, 2, 3, 0, 4, 0, 1, 2, 1};
std::vector<int>::size_type j;
std::vector<int>::size_type i;
vector<vector<int>> my2dArray;
vector<int> dArray;
void calc(vector<int>&, int);
int task;
int sum = 0;
int main() {
for (int i = 0; i < 9;
i++) // iterate through all elements of the given array
{
if (i == 0) // adding the first element
{
my2dArray.resize(my2dArray.size() + 1);
my2dArray.back().push_back(givenArray[i]);
continue;
}
if (givenArray[i] == 0) // re-size if 0 is encountered
{
my2dArray.resize(my2dArray.size() + 1);
}
my2dArray.back().push_back(givenArray[i]);
}
for (std::vector<std::vector<int>>::size_type i = 0; i < my2dArray.size();
i++) {
for (std::vector<int>::size_type j = 0; j < my2dArray[i].size(); j++) {
std::cout << my2dArray[i][j] << ' ';
if (my2dArray[i].size() > 2) {
task = my2dArray[i].size();
calc(my2dArray[i], task);
}
}
std::cout << std::endl;
}
}
void calc(vector<int>& dArray, int task) {
int max = 0;
for (unsigned int j = 0; j < task; j++) {
if (dArray[i] > max)
dArray[i] = max;
}
cout << "\nMax is" << max;
}
However, I want to pass a single row of 2D vector 2dArray to function calc if the number of columns for each row exceeds 2. Function calc aims to find maximum value of all the elements in the passed row. The above program doesn't yield the desired output.
Some improvements:
i and j global variables are not needed, you are declaring the variables of the loops in the loop initialization (ex: for (int i = 0; i < 9; i++), the same for the other loops).
It's better not to used global variables, only when strictly necessary (with careful analysis of why). In this case it's not necessary.
The typedef are for more easy access to inner typedef of the type (ex: size_type).
You were doing the call to calc method in every iteration of the inner loop, and iterating over the same row multiple times, this call should be executed once per row.
Using the size of array givenArray as constant in the code is not recommended, later you could add some elements to the array and forgot to update that constant, it's better to declare a variable and calculated generally (with sizeof).
There is no need to pass the size of the vector to method calc if you are passing the vector.
As recommended earlier it's better to use std::max_element of algorithm header.
If you could use C++11 the givenArray could be converted to an std::vector<int> and maintain the easy initialization.
Code (Tested in GCC 4.9.0)
#include <vector>
#include <iostream>
using namespace std;
typedef std::vector<int> list_t;
typedef std::vector<list_t> list2d_t;
void calc(list_t& dArray, long& actual_max) {
for (unsigned int j = 0; j < dArray.size(); j++) {
if (dArray[j] > actual_max) {
actual_max = dArray[j];
}
}
cout << "Max is " << actual_max << "\n";
}
void calc(list_t& dArray) {
long actual_max = 0;
for (unsigned int j = 0; j < dArray.size(); j++) {
if (dArray[j] > actual_max) {
actual_max = dArray[j];
}
}
cout << "Max is " << actual_max << "\n";
}
int main() {
int givenArray[9] = {1, 2, 3, 0, 4, 0, 1, 2, 1};
int givenArraySize = sizeof(givenArray) / sizeof(givenArray[0]);
list2d_t my2dArray(1);
list_t dArray;
for (int i = 0; i < givenArraySize; i++) {
if (givenArray[i] == 0) {
my2dArray.push_back(list_t());
} else {
my2dArray.back().push_back(givenArray[i]);
}
}
long max = 0;
for (list2d_t::size_type i = 0; i < my2dArray.size(); i++) {
for (list_t::size_type j = 0; j < my2dArray[i].size(); j++) {
std::cout << my2dArray[i][j] << ' ';
}
std::cout << "\n";
if (my2dArray[i].size() > 2) {
// if you need the max of all the elements in rows with size > 2 uncoment bellow and comment other call
// calc(my2dArray[i], max);
calc(my2dArray[i]);
}
}
}
Obtained Output:
1 2 3
Max is 3
4
1 2 1
Max is 2
You have a few problems:
You don't need to loop over j in the main function - your calc function already does this.
Your calc function loops over j, but uses the global variable i when accessing the array.
Your calc function assigns the current max value to the array, rather than assigning the array value to max
Function calc aims to find maximum value of all the elements in the passed row. The above program doesn't yield the desired output.
Instead of writing a function, you could have used std::max_element.
#include <algorithm>
//...
int maxVal = *std::max_element(my2dArray[i].begin(), my2dArray[i].begin() + task);
cout << "\Max is " << maxVal;
Here is my code:
#include <cstdlib>
#include <stdio.h>
#define NUM_READINGS 3
int* readingsTotal;
int* readingsAverage;
int readingsIndex;
using namespace std;
void avgOf(int* toFindAvgOf, int size) {
int i;
for (i = 0; i < size; i++) {
// Add reading to total for each component.
readingsTotal[i] += toFindAvgOf[i];
// Once method has been iterated through n (NUM_READINGS) times:
if (readingsIndex == NUM_READINGS - 1) {
// Set the arithmetic mean.
readingsAverage[i] = readingsTotal[i] / NUM_READINGS;
// Reset the total.
readingsTotal[i] = 0;
}
}
readingsIndex++;
}
int iterate(int findAvgOf) {
int toFindAvgOf[] = {findAvgOf, 20, 30};
avgOf(toFindAvgOf, sizeof (toFindAvgOf));
return readingsAverage[0];
}
int main(int argc, char** argv) {
readingsTotal = (int []){0, 0, 0};
readingsAverage = (int []){0, 0, 0};
int i;
for (i = 0; i < 3; i++) {
int smthd = iterate(12 + i * 2);
printf("%d\n", smthd);
}
return 0;
}
When I run this in netbeans c/c++, it builds with now errors but when it executes it fails and prints:
RUN FAILED (exit value 1, total time: 86ms)
When I go into debug mode it also fails immediately and gives the SIGSEGV error. From reading online I'm guessing there is some issue with the way I am dereferencing a pointer. But I have no clue where exactly it is failing at. I am pretty new to c++ so any help would be great!
In C, the sizeof function returns the size of the object in bytes.
So when you say:
sizeof (toFindAvgOf)
That will return 12 (assuming an int on your system is 4-bytes) thus causing an index out of bounds condition in the avgOf function.
To get the length of the array:
sizeof(toFindAvgOf) / sizeof(int)