I have a problem with the result of my m1 function when I check that some of the array between rank 0 and the last rank is empty and unfortunately none of the workarounds help to solve this problem.
Can anyone help me with this?
Where is the problem in this code?
And how can it be solved?
This is the code:
this is the code:
#include <stdlib.h>
#include <time.h>
#include <mpi.h>
#define N 1000
#define M 1000 / 2
int A[N][N], B[N][N], C[N][N];
int m1[M][M], m2[M][M], m3[M][M], m4[M][M], m5[M][M], m6[M][M], m7[M][M];
int A11[M][M], A12[M][M], A21[M][M], A22[M][M], B11[M][M], B12[M][M], B21[M][M], B22[M][M];
int C11[M][M], C12[M][M], C21[M][M], C22[M][M];
int rank, size, start_row, end_row;
void multiplym1(int mySize, int AA[M][M], int BB[M][M], int CC[M][M], int DD[M][M], int resfinal[M][M], int mystart_row, int myend_row)
{
int result1[mySize][mySize], result2[mySize][mySize];
for (int i = mystart_row; i < myend_row; i++)
{
for (int j = 0; j < mySize; j++)
{
result1[i][j] = AA[i][j] + BB[i][j];
result2[i][j] = CC[i][j] + DD[i][j];
}
}
for (int i = mystart_row; i < myend_row; i++)
{
for (int j = 0; j < mySize; j++)
{
resfinal[i][j] = 0;
for (int k = 0; k < mySize; k++)
{
resfinal[i][j] += (result1[i][k] * result2[k][j]);
}
}
}
}
int main(int argc, char const *argv[])
{
srand(time(NULL));
printf("\n------------------------* Initializing matrices *----------------------\n");
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
start_row = rank * (N / size);
if (rank + 1 == size)
{
end_row = N;
}
else
{
end_row = (rank + 1) * (N / size);
}
// printf("#%d: start is %d and end is %d\n", rank, start_row, end_row);
for (int i = start_row; i < end_row; i++)
{
for (int j = 0; j < N; j++)
{
A[i][j] = rand() % 50;
B[i][j] = rand() % 20;
C[i][j] = 0;
// printf("#%d: A[%d][%d] = %d\n", rank, i, j, A[i][j]);
}
}
// printf("#%d: Done\n\n", rank);
MPI_Barrier(MPI_COMM_WORLD);
// printf("#%d: start \n\n", rank);
start_row = 0;
end_row = 0;
start_row = rank * (M / size);
if (rank + 1 == size)
{
end_row = M;
}
else
{
end_row = (rank + 1) * (M / size);
}
// printf("#%d: start is %d and end is %d\n", rank, start_row, end_row);
for (int i = start_row; i < end_row; i++)
{
for (int j = 0; j < M; j++)
{
A11[i][j] = A[i][j];
A12[i][j] = A[i][j + M];
A21[i][j] = A[i + M][j];
A22[i][j] = A[i + M][j + M];
B11[i][j] = B[i][j];
B12[i][j] = B[i][j + M];
B21[i][j] = B[i + M][j];
B22[i][j] = B[i + M][j + M];
}
}
// printf("#%d: Done\n\n", rank);
MPI_Barrier(MPI_COMM_WORLD);
// printf("#%d: start For M1\n\n", rank);
start_row = 0;
end_row = 0;
start_row = rank * (M / size);
if (rank + 1 == size)
{
end_row = M;
}
else
{
end_row = (rank + 1) * (M / size);
}
printf("#%d: start is %d and end is %d\n", rank, start_row, end_row);
multiplym1(M, A11, A22, B11, B22, m1, start_row, end_row);
MPI_Barrier(MPI_COMM_WORLD);
int *counts = malloc(size * sizeof(int));
int *displs = malloc(size * sizeof(int));
for (int i = 0; i < size; i++)
{
counts[i] = (M / size) * M;
displs[i] = i * (M / size) * M;
}
counts[size - 1] = ((M / size) + (M % size)) * M;
MPI_Gatherv(&m1[start_row][0], counts[rank], MPI_INT, m1, counts, displs, MPI_INT, 0, MPI_COMM_WORLD);
printf("#%d: M1 DONE!!\n", rank);
if (rank == 0)
{
for (int i = 0; i < M; i += 49)
{
for (int j = 0; j < M; j += 100)
{
printf("#%d: m1[%d][%d] = %d\n", rank, i, j, m1[i][j]);
}
}
}
MPI_Finalize();
return 0;
}```
`
Related
I have an array, in which I need to find the number of row, which has the smallest sum of powers. Consider the example array:
1 1 1
2 2 2
3 3 3
The first row, (index = 0), the sum of powers is equal to 3 (1^2 + 1^2 + 1^2 = 3).
The second row, (index = 1), the sum of powers is equal to 12 (2^2 + 2^2 + 2^2 = 12).
The third row, (index = 2), the sum of powers is equal to 27 (3^2 + 3^2 + 3^2 = 27).
But my program shows the wrong result - instead of index 0, it shows index 2. What is the problem?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int ** alloc(int n, int m)
{
int **array, i;
array = malloc(sizeof(int*) * n);
for(i=0; i<n; i++)
array[i] = malloc(sizeof(int) * m);
return array;
}
void show(int **array, int n, int m)
{
int i,j;
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
printf("%d\t", array[i][j]);
}
printf("\n");
}
}
void fill(int **array, int n, int m, int x)
{
int i,j;
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
array[i][j] = x;
}
}
}
void dealloc(int **array, int n, int m)
{
int i;
for(i=0; i<n; i++)
free(array[i]);
free(array);
}
int smallest_powers_sum(int **array, int n, int m)
{
int sum = 0, minsum = 0, i, j, minindex = -1;
for(i=0; i<n; i++)
{
minsum = sum;
sum = 0;
for(j=0; j<m; j++)
{
sum += pow(array[i][j], 2);
}
if(minsum <= sum)
minindex = i;
printf("sum = %d, minsum = %d, minindex = %d\n", sum, minsum, minindex);
}
return minindex;
}
int main(int argc, char **argv)
{
int **array, n1 = 3, m1 = 3;
array = alloc(n1, m1);
fill(array, n1, m1, 1);
array[0][0] = 1;
array[0][1] = 1;
array[0][2] = 1;
array[1][0] = 2;
array[1][1] = 2;
array[1][2] = 2;
array[2][0] = 3;
array[2][1] = 3;
array[2][2] = 3;
int sum = smallest_powers_sum(array, n1, m1);
printf("index = %d\n", sum);
dealloc(array, n1, m1);
return 0;
}
I think you meant this:
if(sum <= minsum ){
minindex = i;
minsum = sum;
}
Also, initially assign integer_max to minsum.
Here's the code:
int smallest_powers_sum(int **array, int n, int m)
{
int sum = 0, minsum = 1000000, i, j, minindex = -1;
for(i=0; i<n; i++)
{
sum = 0;
for(j=0; j<m; j++)
{
sum += pow(array[i][j], 2);
}
if(sum <= minsum ){
minindex = i;
minsum = sum;
}
printf("sum = %d, minsum = %d, minindex = %d\n", sum, minsum, minindex);
}
return minindex;
}
This line kills all your "memory" of previous rows:
minsum = sum;
You should only update minsum together with updating minindex.
Also your condition for updating minindex seems to be the wrong way around.
This would be one way to do (although a bare-bones version):
#define NROWS 3
#define NCOLS 3
int *getminrow(int *p, int n)
{
int minval = *p;
int *minaddr = p;
while (n >= 1) {
if (*p < minval) {
minval = *p;
minaddr = p;
}
n--;
p++;
}
return minaddr;
}
int sumrow(int *p, int n)
{
int sum = 0;
while (n >= 1) {
sum += (*p);
n--;
p++;
}
return sum;
}
int main(void)
{
int *array = malloc(NROWS * NCOLS);
int listsum[NROWS];
int i, j;
array[0 * NROWS + 0] = 1;
array[0 * NROWS + 1] = 1;
array[0 * NROWS + 2] = 1;
array[1 * NROWS + 0] = 2;
array[1 * NROWS + 1] = 2;
array[1 * NROWS + 2] = 2;
array[2 * NROWS + 0] = 3;
array[2 * NROWS + 1] = 3;
array[2 * NROWS + 2] = 3;
for (i = 0; i < NROWS; i++) {
for (j = 0; j < NCOLS; j++) {
array[i * NROWS + j] = pow(array[i * NROWS + j], 2);
}
}
for (i = 0; i < NROWS; i++)
listsum[i] = sumrow(&array[i], NCOLS);
printf("Min row: %d\n", getminrow(listsum, NROWS) - listsum);
return 0;
}
I think there are some problem in your logic. First "if(minisum<=sum)". It must be "if(sum<=minisum)". Second, if you're just using coding like that, then the condition will be considered only condition i and i-1. So, my advice to change the syntax "if(minisum<=sum)" with the following script. (There are new variables that I call minisumtemp).
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int ** alloc(int n, int m)
{
int **array, i;
array = malloc(sizeof(int*) * n);
for(i=0; i<n; i++)
array[i] = malloc(sizeof(int) * m);
return array;
}
void show(int **array, int n, int m)
{
int i,j;
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
printf("%d\t", array[i][j]);
}
printf("\n");
}
}
void fill(int **array, int n, int m, int x)
{
int i,j;
for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
array[i][j] = x;
}
}
}
void dealloc(int **array, int n, int m)
{
int i;
for(i=0; i<n; i++)
free(array[i]);
free(array);
}
int smallest_powers_sum(int **array, int n, int m)
{
//int sum = 0, minsum = 0, i, j, minindex = -1;
int sum = 0, minsum = 0, i, j, minindex = 0, minsumtemp; // add new variable : minsumtemp
for(i=0; i<n; i++)
{
minsum = sum;
sum = 0;
for(j=0; j<m; j++)
{
sum += pow(array[i][j], 2);
}
//if(minsum <= sum) this the problem
// minindex = i;
if (i==0) minsumtemp = sum; // initialized first value for minsumtep
if (sum<=minsumtemp)
{
minindex = i;
minsumtemp = sum;
}
printf("sum = %d, minsum = %d, minindex = %d\n", sum, minsum, minindex);
}
return minindex;
}
int main(int argc, char **argv)
{
int **array, n1 = 3, m1 = 3;
array = alloc(n1, m1);
fill(array, n1, m1, 1);
array[0][0] = 1;
array[0][1] = 1;
array[0][2] = 1;
array[1][0] = 2;
array[1][1] = 2;
array[1][2] = 2;
array[2][0] = 3;
array[2][1] = 3;
array[2][2] = 3;
int sum = smallest_powers_sum(array, n1, m1);
printf("index = %d\n", sum);
dealloc(array, n1, m1);
return 0;
}
I have a program that:
given a sequence of numbers,
sorts even numbers in ascending order, and
sort odd numbers in descending order, and
adds the sorted even numbers to an array followed by the sorted odd numbers.
Example:
Input: 1, 2, 3, 4, 5, 6
Expected output: 2, 4, 6, 5, 3, 1
Actual output: 1578032, 0, 3, 6, 6487408, 0
here is my code:
#include < stdio.h >
int main() {
input();
}
int input() {
int n;
printf("Enter The Number Of Elements You Want To Enter : ");
scanf("%d", & n);
int * ptr, i, ev = 0, od = 0;
ptr = (int * ) calloc(n, sizeof(int));
for (i = 0; i < n; i++) {
printf("Enter Number : ");
scanf("%d", (ptr + i));
if ( * (ptr + i) % 2 == 0) {
ev++;
} else {
od++;
}
}
sorteven( & ptr, ev, od, n);
}
int sorteven(int * ptr, int ev, int od, int n) {
int i, j = 0, swap = 0, * ptreven;
ptreven = (int * ) calloc(ev, sizeof(int));
for (i = 0; i < n; i++) {
if ( * (ptr + i) % 2 == 0) { *
(ptreven + j) = * (ptr + i);
j++;
}
}
for (i = 0; i < ev - 1; i++) {
for (j = 0; j < ev - i - 1; j++) {
if ( * (ptreven + j) > * (ptreven + j + 1)) {
swap = * (ptreven + j); *
(ptreven + j) = * (ptreven + j + 1); *
(ptreven + j + 1) = swap;
}
}
}
sortodd( & ptr, ev, od, n, & ptreven);
}
int sortodd(int * ptr, int ev, int od, int n, int ptreven) {
int i, k = 0, swap = 0, * ptrodd, j;
ptrodd = (int * ) calloc(od, sizeof(int));
for (i = 0; i < n; i++) {
if ( * (ptr + i) % 2 != 0) { *
(ptrodd + k) = * (ptr + i);
k++;
}
}
for (i = 0; i < od - 1; i++) {
for (j = 0; j < od - i - 1; j++) {
if ( * (ptrodd + j) < * (ptrodd + j + 1)) {
swap = * (ptrodd + j); *
(ptrodd + j) = * (ptrodd + j + 1); *
(ptrodd + j + 1) = swap;
}
}
}
merge( & ptr, ev, od, n, & ptreven, & ptrodd);
}
int merge(int * ptr, int ev, int od, int n, int * ptreven, int * ptrodd) {
int * ptrmerge, i, j;
ptrmerge = (int * ) calloc(n, sizeof(int));
for (i = 0; i < ev; i++) { *
(ptrmerge + i) = * (ptreven + i);
}
for (i = ev, j = 0; i < n; i++, j++) { *
(ptrmerge + i) = * (ptrodd + j);
}
display( & ptrmerge, n);
}
int display(int * ptrmerge, int n) {
int i;
printf("OUTPUT : ");
for (i = 0; i < n; i++) {
printf(" %d ", * (ptrmerge + i));
}
}
like this
#include <stdio.h>
#include <stdlib.h>
void input(void);
int main(void){
input();
}
void sorteven(int *ptr, int n);
void sortodd(int *ptr, int n);
void display(int *ptt, int n);
void input(void){
int n;
printf("Enter The Number Of Elements You Want To Enter : ");fflush(stdout);
scanf("%d", &n);
int *ptr, i, ev = 0, od = 0;
if((ptr = calloc(n, sizeof(int)))==NULL){
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < n; i++){
int v;
printf("Enter Number : ");fflush(stdout);
scanf("%d", &v);
if(v % 2 == 0){
ptr[ev++] = v;
} else {
ptr[n - ++od] = v;
}
}
sorteven(ptr, ev);
sortodd(ptr + ev, od);
display(ptr, n);
free(ptr);
}
void sorteven(int *ptr, int n){
//sort to ascending order
int i, j, temp;
for (i = 0; i < n - 1; i++){
for (j = 0; j < n - i - 1; j++){
if(ptr[j] > ptr[j + 1]){
int temp = ptr[j];
ptr[j] = ptr[j + 1];
ptr[j + 1] = temp;
}
}
}
}
void sortodd(int *ptr, int n){
//sort to descending order
int i, j, temp;
for (i = 0; i < n - 1; i++){
for (j = 0; j < n - i - 1; j++){
if(ptr[j] < ptr[j + 1]){
int temp = ptr[j];
ptr[j] = ptr[j + 1];
ptr[j + 1] = temp;
}
}
}
}
void display(int *ptr, int n){
int i;
printf("\nOUTPUT : ");
for (i = 0; i < n; i++){
if(i)
putchar(' ');
printf("%d", ptr[i]);
}
putchar('\n');
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am a beginner in programming and just learned new concepts and started writing code for matrix multiplication but I got confused in pointers and others so I am uploading my code here in seek of guidelines.
#include <stdio.h>
#include <stdlib.h>
int **matrixMultiply(int A[][8], int B[][8], int row);
int main() {
int **A = allocate_matrix(A, 8, 8);
int **B = allocate_matrix(B, 8, 8);
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
A[i][j] = i + j;
A[i][j] = i + j;
}
}
int **C = allocate_matrix(C, 8, 8);
C = matrixMultiply(A, B, 8);
return 0;
}
int **matrixMultiply(int A[][8], int B[][8], int row) {
int **C = allocate_matrix(C, row, row);
if (row == 1) {
C[1][1] = A[1][1] * B[1][1];
} else {
int a11[row/2][row/2], a12[row/2][row/2], a21[row/2][row/2], a22[row/2][row/2];
int b11[row/2][row/2], b12[row/2][row/2], b21[row/2][row/2], b22[row/2][row/2];
int **c11 = allocate_matrix(c11, row/2, row/2);
int **c12 = allocate_matrix(c12, row/2, row/2);
int **c21 = allocate_matrix(c21, row/2, row/2);
int **c22 = allocate_matrix(c22, row/2, row/2);
int i, j;
for (i = 0; i < row/2; i++) {
for (j = 0; j < row/2; j++) {
a11[i][j] = A[i][j];
a12[i][j] = A[i][j + (row/2)];
a21[i][j] = A[i + (row/2)][j];
a22[i][j] = A[i + (row/2)][j + (row/2)];
b11[i][j] = B[i][j];
b12[i][j] = B[i][j + (row/2)];
b21[i][j] = B[i + (row/2)][j];
b22[i][j] = B[i + (row/2)][j + (row/2)];
c11[i][j] = C[i][j];
c12[i][j] = C[i][j + (row/2)];
c21[i][j] = C[i + (row/2)][j];
c22[i][j] = C[i + (row/2)][j + (row/2)];
}
}
c11 = addmatrix(matrixMultiply(a11, b11, row/2),
matrixMultiply(a12, b21, row/2), c11, row/2);
c12 = addmatrix(matrixMultiply(a11, b12, row/2),
matrixMultiply(a22, b22, row/2), c12, row/2);
c21 = addmatrix(matrixMultiply(a21, b11, row/2),
matrixMultiply(a22, b21, row/2), c21, row/2);
c22 = addmatrix(matrixMultiply(a21, b12, row/2),
matrixMultiply(a22, b22, row/2), c22, row/2);
// missing code???
return C;
}
}
int **allocate_matrix(int **matrix, int row, int column) {
matrix = (int **)malloc(row * sizeof(int*));
int i;
for (i = 0; i < row; i++) {
matrix[row] = (int *)malloc(row * sizeof(int));
}
return matrix;
}
void deallocate_matrix(int **matrix, int row) {
int i;
for (i = 0; i < row; i++) {
free(matrix[row]);
}
free(matrix);
}
int **addMatrix(int **a, int **b, int **c, int row) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < row; j++) {
c[i][j] = a[i][j] + b[i][j];
}
}
return c;
}
I reformatted your code so I could analyze it. Indent consistently with 4 spaces, insert spaces around binary operators, after , and ; separators and between keywords and (, this improves readability a lot.
There seems to be missing code in the matrixMultiply function: you allocate the resulting matrix C but you use it as an input to initialize the intermediary matrices c11, c21, c21 and c22, and never actually store anything into C except for the trivial 1x1 case.
The matrix multiplication code seems broken beyond this, the function takes 2 arguments of type int A[][8], int B[][8], but you recursively call it with local arrays a11 to b22 defined as int a11[row/2][row/2]. These types are different, I do not know how the code even compiles.
In the matrix allocation code, you allocate rows with in incorrect size row instead of column. You should use calloc for this so the matrix is initialized to 0, plus you should not pass the initial argument at all:
int **allocate_matrix(int row, int column) {
int **matrix = malloc(row * sizeof(*matrix));
for (int i = 0; i < row; i++) {
matrix[i] = calloc(column, sizeof(*matrix[row]));
}
return matrix;
}
There is also a mistake for the second submatrix multiplication, it should be
c12 = addmatrix(matrixMultiply(a11, b12, row/2),
matrixMultiply(a12, b22, row/2), c12, row/2);
Furthermore, you never free the temporary matrices used for intermediary results. Unlike java, C does not have a garbage collector, you are responsible for releasing blocks of memory when you no longer need them, before they become inaccessible.
Here is a corrected version, with extra functions to print the matrix data and verify the matrix multiplication correctness. I added timings: the recursive method is much slower than the direct method, mostly because of all the extra allocation/deallocation for the intermediary results.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int **matrix_allocate(int row, int column) {
int **matrix = malloc(row * sizeof(*matrix));
for (int i = 0; i < row; i++) {
matrix[i] = calloc(column, sizeof(*matrix[i]));
}
return matrix;
}
void matrix_free(int **matrix, int row) {
for (int i = 0; i < row; i++) {
free(matrix[i]);
}
free(matrix);
}
void matrix_print(const char *str, int **a, int row) {
int min, max, w = 0, n1, n2, nw;
min = max = a[0][0];
for (int i = 0; i < row; i++) {
for (int j = 0; j < row; j++) {
if (min > a[i][j])
min = a[i][j];
if (max < a[i][j])
max = a[i][j];
}
}
n1 = snprintf(NULL, 0, "%d", min);
n2 = snprintf(NULL, 0, "%d", max);
nw = n1 > n2 ? n1 : n2;
for (int i = 0; i < row; i++) {
if (i == 0)
w = printf("%s = ", str);
else
printf("%*s", w, "");
for (int j = 0; j < row; j++) {
printf(" %*d", nw, a[i][j]);
}
printf("\n");
}
fflush(stdout);
}
int **matrix_add(int **a, int **b, int row, int deallocate) {
int **c = matrix_allocate(row, row);
for (int i = 0; i < row; i++) {
for (int j = 0; j < row; j++) {
c[i][j] = a[i][j] + b[i][j];
}
}
if (deallocate & 1) matrix_free(a, row);
if (deallocate & 2) matrix_free(b, row);
return c;
}
int **matrix_multiply(int **A, int **B, int row, int deallocate) {
int **C = matrix_allocate(row, row);
if (row == 1) {
C[0][0] = A[0][0] * B[0][0];
} else {
int row2 = row / 2;
int **a11 = matrix_allocate(row2, row2);
int **a12 = matrix_allocate(row2, row2);
int **a21 = matrix_allocate(row2, row2);
int **a22 = matrix_allocate(row2, row2);
int **b11 = matrix_allocate(row2, row2);
int **b12 = matrix_allocate(row2, row2);
int **b21 = matrix_allocate(row2, row2);
int **b22 = matrix_allocate(row2, row2);
for (int i = 0; i < row2; i++) {
for (int j = 0; j < row2; j++) {
a11[i][j] = A[i][j];
a12[i][j] = A[i][j + row2];
a21[i][j] = A[i + row2][j];
a22[i][j] = A[i + row2][j + row2];
b11[i][j] = B[i][j];
b12[i][j] = B[i][j + row2];
b21[i][j] = B[i + row2][j];
b22[i][j] = B[i + row2][j + row2];
}
}
int **c11 = matrix_add(matrix_multiply(a11, b11, row2, 0),
matrix_multiply(a12, b21, row2, 0), row2, 1+2);
int **c12 = matrix_add(matrix_multiply(a11, b12, row2, 1),
matrix_multiply(a12, b22, row2, 1), row2, 1+2);
int **c21 = matrix_add(matrix_multiply(a21, b11, row2, 2),
matrix_multiply(a22, b21, row2, 2), row2, 1+2);
int **c22 = matrix_add(matrix_multiply(a21, b12, row2, 1+2),
matrix_multiply(a22, b22, row2, 1+2), row2, 1+2);
for (int i = 0; i < row2; i++) {
for (int j = 0; j < row2; j++) {
C[i][j] = c11[i][j];
C[i][j + row2] = c12[i][j];
C[i + row2][j] = c21[i][j];
C[i + row2][j + row2] = c22[i][j];
}
}
matrix_free(c11, row2);
matrix_free(c12, row2);
matrix_free(c21, row2);
matrix_free(c22, row2);
}
if (deallocate & 1) matrix_free(A, row);
if (deallocate & 2) matrix_free(B, row);
return C;
}
int **matrix_multiply_direct(int **A, int **B, int row, int deallocate) {
int **C = matrix_allocate(row, row);
for (int i = 0; i < row; i++) {
for (int j = 0; j < row; j++) {
int x = 0;
for (int k = 0; k < row; k++) {
x += A[i][k] * B[k][j];
}
C[i][j] = x;
}
}
if (deallocate & 1) matrix_free(A, row);
if (deallocate & 2) matrix_free(B, row);
return C;
}
int main(int argc, char **argv) {
int n = argc < 2 ? 8 : atoi(argv[1]);
int **A = matrix_allocate(n, n);
int **B = matrix_allocate(n, n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
A[i][j] = i + j;
B[i][j] = i + j;
}
}
matrix_print("A", A, n);
matrix_print("B", B, n);
if ((n & (n - 1)) == 0) {
/* recursive method can be applied only to powers of 2 */
clock_t ticks = -clock();
int **C = matrix_multiply(A, B, n, 0);
ticks += clock();
matrix_print("C = A * B", C, n);
printf("%d ticks\n", ticks);
matrix_free(C, n);
}
clock_t ticks = -clock();
int **D = matrix_multiply_direct(A, B, n, 1+2);
ticks += clock();
matrix_print("D = A * B", D, n);
printf("%d ticks\n", ticks);
matrix_free(D, n);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
float average_score(int** array_score)
{
int i, j;
int sum = 0;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
sum += *(*(array_score + i) + j);
}
}
printf("sum / 16 = %d\n", sum / 16);
return (float) sum / 16;
}
int lowest_score(int** array_score)
{
int i, j;
int temp = **array_score;
for(i = 0; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
if(temp > *(*(array_score + i) + j))
//------
temp = *(*(array_score + i) + j);
printf("%d ",*(*(array_score + i) + j));
}
//--
printf("\n");
}
printf("low_score = %d\n", temp);
return temp;
}
int main(int argc, char** argv)
{
int **array_score = NULL;
int i = 0;
int j = 0;
//Create a two-dimensional array
array_score = (int **) malloc(4 * sizeof(int *));
for(i = 0; i <= 4; i++)
array_score[i] = (int *)malloc(4 * sizeof(int));
//--
for(i = 0; i < 4; i++)
{
printf("Please enter the student_%d four grades, (separated with a space )\n", i+1);
int ret = scanf("%d %d %d %d", (*(array_score + i) + 0), (*(array_score + i) + 1),
(*(array_score + i) + 2), (*(array_score + i) + 3));
fflush(stdin);
if(4 != ret)
i--;
}
//There is something wrong with the function return value
float ave_score = average_score(array_score);
//--
int low_score = lowest_score(array_score);
//The output
printf("average score: %d\n lowest score: %d\n", ave_score, low_score);
return 0;
}
This allocates space for 4 pointers and then writes 5, since i takes on the values 0, 1, 2, 3 and 4:
array_score = (int **) malloc(4 * sizeof(int *));
for(i = 0; i <= 4; i++)
array_score[i] = (int *)malloc(4 * sizeof(int));
Note that in C you shouldn't cast the return from malloc. There's an answer on Stackoverflow telling all the details why this is not helpful.
I have this parallel Gaussian elimination code. A segmentation error happens upon calling either MPI_Gather function calls. I know such error may rise if memory is not allocated properly for either buffers. But I cannot see any wrong with the memory management code.
Can someone help?
Thanks.
Notes:
The program reads from a .txt file in the same directory called input.txt.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mpi.h"
/*void print2dAddresses(double** array2d, int rows, int cols)
{
int i;
for(i = 0; i < rows; i++)
{
int j;
for(j = 0; j < cols; j++)
{
printf("%d ", &(array2d[i][j]));
}
printf("\n");
}
printf("------------------------------------");
}*/
double** newMatrix(int rows, int cols)
{
double *data = (double*) malloc(rows * cols * sizeof(double));
double **array= (double **)malloc(rows * sizeof(double*));
int i;
for (i=0; i<rows; i++)
array[i] = &(data[cols*i]);
return array;
}
void freeMatrix(double** mat)
{
free(mat[0]);
free(mat);
}
double** new2dArray(int nrows, int ncols)
{
int i;
double** array2d;
array2d = (double**) malloc(nrows * sizeof(double*));
for(i = 0; i < nrows; i++)
{
array2d[i] = (double*) malloc(ncols * sizeof(double));
}
return array2d;
}
double* new1dArray(int size)
{
return (double*) malloc(size * sizeof(double));
}
void free2dArray(double** array2d, int nrows)
{
int i;
for(i = 0; i < nrows; i++)
{
free(array2d[i]);
}
free(array2d);
}
void print2dArray(double** array2d, int nrows, int ncols)
{
int i, j;
for(i = 0; i < nrows; i++)
{
for(j = 0; j < ncols; j++)
{
printf("%lf ", array2d[i][j]);
}
printf("\n");
}
printf("----------------------\n");
}
void print1dArray(double* array, int size)
{
int i;
for(i = 0; i < size; i++)
{
printf("%lf\n", array[i]);
}
printf("----------------------\n");
}
void read2dArray(FILE* fp, double** array2d, int nrows, int ncols)
{
int i, j;
for(i = 0; i < nrows; i++)
{
for(j = 0; j < ncols; j++)
{
fscanf(fp, "%lf", &(array2d[i][j]));
}
}
}
void read1dArray(FILE* fp, double* array, int size)
{
int i;
for(i = 0; i < size; i++)
{
fscanf(fp, "%lf", &(array[i]));
}
}
void readSymbols(char* symbols, int size, FILE* fp)
{
int i;
for(i = 0; i < size; i++)
{
char c = '\n';
while(c == '\n' | c == ' ' | c == '\t' | c == '\r')
fscanf(fp, "%c", &c);
symbols[i] = c;
}
}
void printSolution(char* symbols, double* x, int size)
{
int i;
for(i = 0; i < size; i++)
{
printf("%c = %lf\n", symbols[i], x[i]);
}
}
double* copy_1d_array(double* original, int size)
{
double* copy_version;
int i;
copy_version = (double*) malloc(size * sizeof(double));
for(i = 0; i < size; i++)
{
copy_version[i] = original[i];
}
return copy_version;
}
int main(int argc, char** argv)
{
int p, rank, i, j, k, l, msize, rowsPerProcess, remainder, startingRow, dest, rowCounter, remainingRows, neededProcesses;
double **A, *b, *x, **smallA, *currentRow, *smallB, currentB, **receivedA, *receivedB;
char *symbols;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &p);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(rank == 0)
{
FILE* fp;
fp = fopen("input.txt", "r");
fscanf(fp, "%d", &msize);
A = newMatrix(msize, msize);
b = new1dArray(msize);
x = new1dArray(msize);
symbols = (char*) malloc(msize * sizeof(char));
read2dArray(fp, A, msize, msize);
read1dArray(fp, b, msize);
readSymbols(symbols, msize, fp);
fclose(fp);
/*print2dArray(A, msize, msize);
print1dArray(b, msize);*/
}
MPI_Bcast(&msize, 1, MPI_INT, 0, MPI_COMM_WORLD);
for(i = 0; i < (msize - 1); i++)
{
int maxIndex;
double maxCoef, tmp, r;
/*finding max row*/
if(rank == 0)
{
maxIndex = i;
maxCoef = fabs(A[i][i]);
for(j = i + 1; j < msize; j++)
{
if(fabs(A[j][i]) > maxCoef)
{
maxCoef = A[j][i];
maxIndex = j;
}
}
/*swapping the current row with the max row*/
for(j = 0; j < msize; j++)
{
tmp = A[i][j];
A[i][j] = A[maxIndex][j];
A[maxIndex][j] = tmp;
}
tmp = b[i];
b[i] = b[maxIndex];
b[maxIndex] = tmp;
/*elimination*/
/*for(j = i + 1; j < msize; j++)
{
double r = A[j][i] / A[i][i];
subtracting r * row i from row j
for(k = i; k < msize; k++)
{
A[j][k] -= r * A[i][k];
}
b[j] -= r * b[i];
}*/
/*parallel elimination*/
startingRow = i + 1;
neededProcesses = p;
remainingRows = msize - startingRow;
if(remainingRows < neededProcesses)
{
neededProcesses = remainingRows;
}
rowsPerProcess = remainingRows / neededProcesses;
remainder = remainingRows % neededProcesses;
}
MPI_Bcast(&startingRow, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(&rowsPerProcess, 1, MPI_INT, 0, MPI_COMM_WORLD);
if(rank == 0)
{
currentRow = copy_1d_array(A[startingRow-1], msize);
currentB = b[startingRow-1];
}
else
{
currentRow = new1dArray(msize);
}
MPI_Bcast(currentRow, msize, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Bcast(¤tB, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
if(rank == 0)
{
receivedA = newMatrix(remainingRows, msize);
receivedB = new1dArray(remainingRows);
}
smallA = newMatrix(rowsPerProcess, msize);
smallB = new1dArray(rowsPerProcess);
MPI_Scatter(&(A[startingRow][0]), rowsPerProcess*msize, MPI_DOUBLE, &(smallA[0][0]), rowsPerProcess*msize, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Scatter(&(b[startingRow]), rowsPerProcess, MPI_DOUBLE, &(smallB[0]), rowsPerProcess, MPI_DOUBLE, 0, MPI_COMM_WORLD);
for(j = 0; j < rowsPerProcess; j++)
{
r = smallA[j][startingRow-1] / currentRow[startingRow-1];
for(k = 0; k < msize; k++)
{
smallA[j][k] -= r * currentRow[k];
}
smallB[j] -= r * currentB;
}
MPI_Gather(&(smallA[0][0]), rowsPerProcess*msize, MPI_DOUBLE, &(receivedA[0][0]), rowsPerProcess*msize, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gather(&(smallB[0]), rowsPerProcess, MPI_DOUBLE, &(receivedB[0]), rowsPerProcess, MPI_DOUBLE, 0, MPI_COMM_WORLD);
freeMatrix(smallA);
free(smallB);
if(rank == 0)
{
for(j = 0; j < remainingRows; j++)
{
for(k = 0; k < msize; k++)
{
A[j+startingRow][k] = receivedA[j][k];
}
b[j+startingRow] = receivedB[j];
}
free(currentRow);
freeMatrix(receivedA);
free(receivedB);
}
if(rank == 0)
{
if(remainder > 0)
{
for(j = (msize - remainder); j < msize; j++)
{
r = A[j][i] / A[i][i];
for(k = 0; k < msize; k++)
{
A[j][k] -= r * A[i][k];
}
b[j] -= r * b[i];
}
}
}
}
if(rank == 0)
{
/*backward substitution*/
for(i = msize - 1; i >= 0; i--)
{
x[i] = b[i];
for(j = msize - 1; j > i; j--)
{
x[i] -= A[i][j] * x[j];
}
x[i] /= A[i][i];
}
printf("solution = \n");
//print1dArray(x, msize);
printSolution(symbols, x, msize);
freeMatrix(A);
free(b);
free(x);
free(symbols);
}
MPI_Finalize();
return 0;
}
Input File:
3
1 1 1
1 1 3
2 1 4
4
9
12
x
y
z
It might be this: &(receivedA[0][0]) on processes where rank != 0. You're indexing an array that hasn't been allocated. You might have to create another pointer, like this:
if(rank == 0)
{
receivedA = newMatrix(remainingRows, msize);
recievedAHead = &(receivedA[0][0]);
receivedB = new1dArray(remainingRows);
}
else {
recievedAHead = NULL;
}
and use recievedAHead in the MPI_Gather call.