How to send and receive data in mpi c++ - c++

I am a beginner in MPI programing and I am trying to do a matrix-vector multiplication (Ax=b).
let say A matrix is as follows,
|3 2 5|
matrix A= |4 3 1|
|2 4 2|
I divided A matrix into two matrix A1 and A2 as follows
|1 2 3|
matrix A1= |3 2 1|
|1 2 0|
|2 0 2|
matrix A2= |1 1 0|
|1 2 2|
The x vector is,
| 2 |
vector x= | 1 |
| 3 |
I need to calculate Ax=b such a way that the process number 1 does the A1 * x multiplication and gives C1 and process number 2 does the A2 * x multiplication and gives C2 and at the end the sum of C1 and C2 will be wrapped up in C. when I run the code through cmd it stops working and I don't know what is the problem. I would be really grateful if you could help me to find out what is the problem in code,
here is my code,
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<fstream>
#include<vector>
#include<iterator>
#include<sstream>
#include<string>
#include<cstdlib>
#include<cmath>
#include<stdio.h>
#include<conio.h>
#include<algorithm>
#include<ctime>
#include<iomanip>
#include<mpi.h>
#include<time.h>
#include<assert.h>
using namespace std;
void Initialise(int **res, int rows, int cols);
void Multiply(int **res, int **A, int **B, int aRows, int aCols, int bRows, int bCols);
void timestamp();
//**********************************************************
/* |3 2 5|
matrix A= |4 3 1|
|2 4 2|
matrix A is divided into two matrix A1,A2
|1 2 3|
matrix A1= |3 2 1|
|1 2 0|
|2 0 2|
matrix A2= |1 1 0|
|1 2 2|
| 2 |
vector x= | 1 |
| 3 |
| 23 |
C = | 14 |
| 14 |
//*********************************************************
*/
int main(int argc,char **argv)
{
int id, p;
MPI_Status status;
// p -> no. of processes
// id -> process id
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
MPI_Comm_size(MPI_COMM_WORLD, &p);
cout << p << endl;
char processor_name[MPI_MAX_PROCESSOR_NAME];
int name_len;
MPI_Get_processor_name(processor_name, &name_len);
if (id == 0)// master
{
wtime = MPI_Wtime();
int aRows = 3;
int aCols = 3;
int bRows = 3;
int bCols = 1;
int** A = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
A[i] = new int[aCols];
}
int** A1 = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
A1[i] = new int[aCols];
}
int** A2 = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
A2[i] = new int[aCols];
}
int** B = new int*[bRows];
for (int i = 0; i < bRows; i++)
{
B[i] = new int[bCols];
}
//***************************************
A[0][0] = 3;
A[0][1] = 2;
A[0][2] = 5;
A[1][0] = 4;
A[1][1] = 3;
A[1][2] = 1;
A[2][0] = 2;
A[2][1] = 4;
A[2][2] = 2;
B[0][0] = 2;
B[1][0] = 1;
B[2][0] = 3;
//**************************************
A1[0][0] = 1;
A1[0][1] = 2;
A1[0][2] = 3;
A1[1][0] = 3;
A1[1][1] = 2;
A1[1][2] = 1;
A1[2][0] = 1;
A1[2][1] = 2;
A1[2][2] = 0;
//**************************************
A2[0][0] = 2;
A2[0][1] = 0;
A2[0][2] = 2;
A2[1][0] = 1;
A2[1][1] = 1;
A2[1][2] = 0;
A2[2][0] = 1;
A2[2][1] = 2;
A2[2][2] = 2;
//*************************************
B[0][0] = 2;
B[1][0] = 1;
B[2][0] = 3;
//*************************************
int** C;
C = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
C[i] = new int[bCols];
}
//************************************
int** C1;
C1 = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
C1[i] = new int[bCols];
}
//************************************
int** C2;
C2 = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
C2[i] = new int[bCols];
}
//***********************************
Multiply(C, A, B, aRows, aCols, bRows, bCols);
for (int i = 0; i < aRows; i++)
{
for (int j = 0; j < bCols; j++)
{
std::cout << C[i][j] << ' ';
}
std::cout << '\n';
}
MPI_Send(&aRows, 1, MPI_INT, 1, 1, MPI_COMM_WORLD);
MPI_Send(&aCols, 1, MPI_INT, 1, 2, MPI_COMM_WORLD);
MPI_Send(&bRows, 1, MPI_INT, 1, 3, MPI_COMM_WORLD);
MPI_Send(&bCols, 1, MPI_INT, 1, 4, MPI_COMM_WORLD);
MPI_Send(&aRows, 1, MPI_INT, 2, 5, MPI_COMM_WORLD);
MPI_Send(&aCols, 1, MPI_INT, 2, 6, MPI_COMM_WORLD);
MPI_Send(&bRows, 1, MPI_INT, 2, 7, MPI_COMM_WORLD);
MPI_Send(&bCols, 1, MPI_INT, 2, 8, MPI_COMM_WORLD);
MPI_Send(&A1, aRows*aCols, MPI_INT, 1, 9, MPI_COMM_WORLD);
MPI_Send(&B , bRows*bCols, MPI_INT, 1, 10, MPI_COMM_WORLD);
MPI_Send(&A2, aRows*aCols, MPI_INT, 2, 11, MPI_COMM_WORLD);
MPI_Send(&B, bRows*bCols, MPI_INT, 2, 12, MPI_COMM_WORLD);
}
for (id=1;id<3;id++)
{
if (id == 1)
{
int aRows, aCols, bRows, bCols;
MPI_Recv(&aRows, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, &status);
printf("receive data:%d", aRows);
MPI_Recv(&aCols, 1, MPI_INT, 0, 2, MPI_COMM_WORLD, &status);
printf("receive data:%d", aCols);
MPI_Recv(&bRows, 1, MPI_INT, 0, 3, MPI_COMM_WORLD, &status);
printf("receive data:%d", bRows);
MPI_Recv(&bCols, 1, MPI_INT, 0, 4, MPI_COMM_WORLD, &status);
printf("receive data:%d", bCols);
//int s = status.MPI_SOURCE;
//int t = status.MPI_TAG;
int** A1 = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
A1[i] = new int[aCols];
}
int** B = new int*[bRows];
for (int i = 0; i < bRows; i++)
{
B[i] = new int[bCols];
}
int** C1 = new int*[bRows];
for (int i = 0; i < bRows; i++)
{
C1[i] = new int[bCols];
}
//***********************************************************
MPI_Recv(&A1, aRows*aCols, MPI_INT, 0, 9, MPI_COMM_WORLD, &status);
printf("receive data:%d", A1);
MPI_Recv(&B , aRows*aCols, MPI_INT, 0, 10, MPI_COMM_WORLD, &status);
printf("receive data:%d", B);
Multiply(C1, A1, B, aRows, aCols, bRows, bCols);
for (int i = 0; i < aRows; i++)
{
for (int j = 0; j < bCols; j++)
{
cout << C1[i][j] << endl;
}
}
}
else
{
int aRows, aCols, bRows, bCols;
MPI_Recv(&aRows, 1, MPI_INT, 0, 5, MPI_COMM_WORLD, &status);
MPI_Recv(&aCols, 1, MPI_INT, 0, 6, MPI_COMM_WORLD, &status);
MPI_Recv(&bRows, 1, MPI_INT, 0, 7, MPI_COMM_WORLD, &status);
MPI_Recv(&bCols, 1, MPI_INT, 0, 8, MPI_COMM_WORLD, &status);
int** A2 = new int*[aRows];
for (int i = 0; i < aRows; i++)
{
A2[i] = new int[aCols];
}
int** B = new int*[bRows];
for (int i = 0; i < bRows; i++)
{
B[i] = new int[bCols];
}
int** C2 = new int*[bRows];
for (int i = 0; i < bRows; i++)
{
C2[i] = new int[bCols];
}
MPI_Recv(&A2, aRows*aCols, MPI_INT, 0, 11, MPI_COMM_WORLD, &status);
printf("receive data:%d", A2);
MPI_Recv(&B , aRows*aCols, MPI_INT, 0, 12, MPI_COMM_WORLD, &status);
printf("receive data:%d", B);
//**************************************************************
MPI_Status status;
Multiply(C2, A2, B, aRows, aCols, bRows, bCols);
for (int i = 0; i < aRows; i++)
{
for (int j = 0; j < bCols; j++)
{
cout << C2[i][j] << endl;
}
}
}
//MPI_Recv(&(C1[0][0]), aRows*bCols, MPI_INT, 0, tag, MPI_COMM_WORLD,&status);
}
MPI_Finalize();
return 0;
}
void Multiply(int **res, int **A, int **B, int aRows, int aCols, int bRows, int bCols)
{
if (aCols != bRows)
return;
for (int i = 0; i < aRows; i++)
{
for (int j = 0; j < bCols; j++)
{
res[i][j] = 0;
for (int k = 0; k < aCols; k++)
{
res[i][j] += A[i][k] * B[k][j];
}
}
}
}
void Initialise(int **res, int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
res[i][j] = 0;
}
}
}

Related

How to evenly distribute an array with Scatterv

My program is meant to take an array size and the elements of that particular array from the user.
However, I want the program to be able to distribute the array elements evenly for any number of processors used.
I think the problem is on the displs array, but even after countless try-outs, I don't seem to be reaching any logical conclusion.
Let's say I enter a sequence of 7 numbers -> 1,2,3,4,5,6,7
I will have an output as such:
processor 0
arr[0] = 1
arr[1] = 2
arr[2] = 3
processor 1
arr[0] = 4
arr[1] = 5
processor 2
arr[0] = 7
arr[1] = 32767
The code is the following:
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_SIZE 100
int main(int argc, char **argv)
{
int myrank, wsize;
int i,N;
int *arr,*displs, *arr_r, *sendcount;
int sum1=0;
int portion,remainder,x,y;
int root;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Comm_size(MPI_COMM_WORLD, &wsize);
if(myrank == 0)
{
printf("Enter number N of integers\n");
scanf("%d", &N);
arr = (int*)malloc(N*sizeof(int));
for(i = 0; i < N; i++)
{
printf("Enter number %d\n", i+1);
scanf("%d",&arr[i]);
}
}
MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
portion = N / wsize;
remainder = N % wsize;
x = portion;
y = portion +1;
displs = (int*)malloc(N*sizeof(int));
sendcount = (int*)malloc(N*sizeof(int));
for(i=0; i < N; i++)
{
if(myrank < remainder)
{
sendcount[i] = portion + (remainder);
displs[i] = (portion + (remainder)) * i;
}
else if(remainder == 0)
{
sendcount[i] = portion;
displs[i] = portion *i;
}
else
{
sendcount[i] = portion;
displs[i] = portion * i;
}
}
arr_r = (int*)malloc(N *sizeof(int));
MPI_Scatterv(arr, sendcount, displs, MPI_INT, arr_r, N, MPI_INT, 0, MPI_COMM_WORLD);
if(myrank < remainder)
{
printf("process %d \n",myrank);
for(i = 0; i < portion + 1; i++)
{
printf("Arr[%d] = %d\n",i,arr_r[i]);
}
}
else if(remainder == 0)
{
printf("process %d \n",myrank);
for(i = 0; i < portion; i++)
{
printf("Arr[%d] = %d\n",i,arr_r[i]);
}
}
else
{
printf("process %d \n",myrank);
for(i = 0; i < portion; i++)
{
printf("Arr[%d] = %d\n",i,arr_r[i]);
}
}
MPI_Finalize();
return 0;
}

Matrix inverter returning the wrong inverse

This code is meant to find the inverse of a matrix, it almost does this. The last row of numbers is incorrect and I am not sure why.
This is not the best way to find the inverse, however it is how I need to do it for my homework assignment.
I have reworked the power function a couple times, so it should be correct now.
The method being used is B=I-A, A^-1 = I+B+B^2+B^3...(all the way to B^20).
#include <iostream>
#include <iomanip>
using namespace std;
void multiplinator(double invA[][3], double A[][3], double y[][3]) //multiplies the matrix
{
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
y[i][j] = 0;
for(int k = 0; k < 3; k++)
{
y[i][j] += invA[i][k] * A[k][j];
}
}
}
}
void printinator(double a[3][3]) //prints a matrix
{
for(int i=0; i<=2; i++)
{
for(int j=0; j<=2; j++)
cout << fixed << setprecision(2) << setw(12) << a[i][j] << " ";
cout << endl;
}
cout << endl;
}
void substitinator(double I[][3], double A[][3], double B[][3]) //Matrix subtraction
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
B[i][j] = I[i][j] - A[i][j];
}
void additinator(double I[3][3], double B[][3], double invA[][3]) //Matrix addition
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
invA[i][j] = I[i][j] + B[i][j];
}
void powernator(double B[][3],double pB[][3], int p) //function which is supposed to raise a matrix to a certain power
{
double temp[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
int i,j,w,k;
for(i = 0 ; i < 2 ; ++ i )
for(j = 0 ; j < 2 ; ++ j )
pB[i][j] = ( i == j ) ;
for(w = 0; w < p; w++)
{
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
{
temp[i][j]=0;
for(k=0;k<2;k++)
{
temp[i][j] += pB[i][k] * B[k][j];
}
}
}
for(i = 0; i < 2; i++){
for(j = 0; j < 2; j++)
{
pB[i][j] = temp[i][j];
}
}
}
}
void gettem(double pB[][3], double invA[][3]) //Matrix addition of power of B
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
invA[i][j] += pB[i][j];
}
int main()
{
double A[3][3] = { {1./2, 1, 0} , {0, 2./3, 0} , {-1./2, -1, 2./3} };
double invA[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
double I[3][3] = { {1, 0, 0} , {0, 1, 0} , {0, 0, 1} };
double B[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
double pB[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
double y[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
substitinator(I,A,B);
additinator(I,B,invA);
for(int p = 2; p <= 20; p++)
{
powernator(B,pB,p);
gettem(pB, invA);
}
cout << "\n\t\t Inverse:" << endl;
printinator(invA);
cout << "\n\t\t invA * A:" << endl;
multiplinator(invA, A, y);
printinator(y);
}
I agree with the #1201ProgramAlarm, your powernator() function is wrong, you should make sure all the for loop condition is < 3 not < 2
void powernator(double B[3][3],double pB[3][3], int p) //function which is supposed to raise a matrix to a certain power
{
double temp[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
int i,j,w,k;
for(i = 0 ; i < 3 ; ++ i )
for(j = 0 ; j < 3 ; ++ j )
pB[i][j] = ( i == j ) ;
for(w = 0; w < p; w++)
{
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
temp[i][j]=0;
for(k=0;k<3;k++)
{
temp[i][j] += pB[i][k] * B[k][j];
}
}
}
for(i = 0; i < 3; i++){
for(j = 0; j < 3; j++)
{
pB[i][j] = temp[i][j];
}
}
}
}
The results are:
Inverse:
2.00 -3.00 0.00
0.00 1.50 0.00
1.50 0.00 1.50
invA * A:
1.00 0.00 0.00
0.00 1.00 0.00
-0.00 0.00 1.00
Hope this helps.

Working on a matrix inverter and my exponential loop is not working for some reason

I am working on a matrix inverter and I have it almost done but for some reason the function that is supposed to raise the matrix to a certain value is not working, I have isolated the function on its own and it has worked just fine. But for some reason is not working in this program
Isolated
#include <iomanip>
#include <stdio.h>
using namespace std;
void printano(double a[3][3])
{
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
cout << fixed << setprecision(2) << setw(12) << a[i][j] << " ";
cout << endl;
}
}
void powernator(double r[][3],double B[][3], int p)
{
double temp[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
int n = 3;
for (int b = 0; b < n; b++)
{
for (int d = 0; d < n; d++)
{
r[b][d] = B[b][d];
}
}
for (int i = 0; i < p - 1; i++)
{
int sum = 0;
for (int b = 0; b < n; b++)
{
for (int d = 0; d < n; d++)
{
for (int k = 0; k < n; k++)
{
sum += B[b][k] * r[k][d];
}
temp[b][d] = sum;
sum = 0;
}
}
for (int b = 0; b < n; b++)
{
for (int d = 0; d < n; d++)
{
r[b][d] = temp[b][d];
}
}
}
}
int main()
{
double B[3][3] = { {1, 2, 3} , {4, 5, 6} , {7, 8, 9} };
double r[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
powernator(r,B,3);
printano(r);
}
The actual code
#include <iostream>
#include <iomanip>
#include <cmath>
#include <stdio.h>
using namespace std;
void multiplinator(double x[][3], double y[][3], double z[][3]) //At the end I double check to make sure the value is correct as it needs to equal the identity matrix
{
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
for(int k = 0; k < 3; k++)
{
z[i][j] += x[i][k] * y[k][j];
}
}
}
}
void printinator(double a[3][3]) //prints a matrix
{
for(int i=0; i<=2; i++)
{
for(int j=0; j<=2; j++)
cout << fixed << setprecision(4) << setw(12) << a[i][j] << " ";
cout << endl;
}
cout << endl;
}
void sub(double as[3][3], double in[][3], double B[][3]) //Matrix subtraction
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
B[i][j] = in[i][j] - as[i][j];
}
void powernator(double r[][3],double B[][3], int p) //Array which is supposed to raise a matrix to a certain power
{
double temp[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
int n = 3;
for (int b = 0; b < n; b++)
{
for (int d = 0; d < n; d++)
{
r[b][d] = B[b][d];
}
}
for (int i = 0; i < p - 1; i++)
{
int sum = 0;
for (int b = 0; b < n; b++)
{
for (int d = 0; d < n; d++)
{
for (int k = 0; k < n; k++)
{
sum += B[b][k] * r[k][d];
}
temp[b][d] = sum;
sum = 0;
}
}
for (int b = 0; b < n; b++)
{
for (int d = 0; d < n; d++)
{
r[b][d] = temp[b][d];
}
}
}
}
void gettem(double r[][3], double in[][3], double inm[][3]) //Supposed to return the final value, aka, the inverse matrix, as a^-1 = I + B^1 +B^2...
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
inm[i][j] = in[i][j] + r[i][j];
}
}
int main()
{
double a[3][3] = { {1./2, 1, 0} , {0, 2./3, 0} , {-1./2, -1, 2./3} };
double as[3][3] ={ {1./2, 1, 0} , {0, 2./3, 0} , {-1./2, -1, 2./3} };
double in[3][3] = { {1, 0, 0} , {0, 1, 0} , {0, 0, 1} };
double B[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
double r[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
double inm[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
double z[3][3] = { {0, 0, 0} , {0, 0, 0} , {0, 0, 0} };
cout << "\n\t\t Original : " << endl;
printinator(a);
sub(as,in,B);
printinator(B);
powernator(r,B,2);
printinator(r); //testing the power function, not working
/*for(int n = 0; n < 20; n++) //Final part of the code commented out for debug, this loop is meant to add up B^n where n is from 1 - 20
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
r[i][j] += B[i][j];
}
gettem(r,in,inm);
cout << "\n\t\t Inverse: " << endl;
printinator(inm);
multiplinator(as,a,z);
cout << "\n\t\t multi: " << endl;
printinator(z);
*/
}
Isolated Code
powernator(r,B,3);
Actual Code.
powernator(r,B,2);
parameter p is differ..

Remove duplicates from an unsorted array

I'm trying to create a function to remove duplicates from an unsorted int array. I have a solution that works for more examples, but it's failing with the following input:
#include<iostream>
using namespace std;
int removeDuplicates(int arr[], int n)
{
int j = 0;
for (int i=0; i < n; i++){
for(int j=0;j<=i;j++){
if(arr[i]==arr[j]){
n--;
for (int k=i; k<n; k++){
arr[k]=arr[k+1];
}
}
}
}
return n;
}
// Driver code
int main()
{
int arr[] = {0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1};
int n = sizeof(arr) / sizeof(arr[0]);
n = removeDuplicates(arr, n);
for (int i=0; i<n; i++)
cout << arr[i] << " ";
return 0;
}
The output for this arr example is 0 0 1 0 0 and should be 0 1.
Do you see where is the problem? Thank you
Consider using std::set<int> to record numbers you've already seen, and using a STL algorithm to perform the removal:
#include<iostream>
#include<algorithm>
#include<functional>
#include<set>
// Driver code
int main()
{
int arr[] = {0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1};
std::set<int> duplicates;
auto it = std::remove_if(std::begin(arr), std::end(arr), [&duplicates](int i) {
return !duplicates.insert(i).second;
});
size_t n = std::distance(std::begin(arr), it);
for (size_t i = 0; i < n; i++)
std::cout << arr[i] << " ";
return 0;
}
The effect of this code is that all duplicates are moved to the end of the array, and the iterator returned by std::remove_if indicates the end of the new list. So iterating between the beginning and that iterator gives you the array without the duplicates.
look over inner loop you forgot to decrement i
#include<iostream>
using namespace std;
int removeDuplicates(int arr[], int n)
{
int j = 0;
for (int i=0; i < n; i++){
for(int j=0;j<i;j++){
if(arr[i]==arr[j]){
n--;
for (int k=i; k<n; k++){
arr[k]=arr[k+1];
}
i--; // you forgot to decrement i
}
}
}
return n;
}
// Driver code
int main()
{
int arr[] = {0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1};
int n = sizeof(arr) / sizeof(arr[0]);
n = removeDuplicates(arr, n);
for (int i=0; i<n; i++)
cout << arr[i] << " ";
return 0;
}
In your function
int removeDuplicates(int arr[], int n)
{
int j = 0;
for (int i=0; i < n; i++){
for(j=i+1;j<n;)
{
if(a[i]==a[j])
{
for(int k=j;k<n-1;++k)
arr[k]=arr[k+1];
--n;
}
else
++j;
}
}
return n;
}
Increment j only when the two values do not match. Or else it will skip few values
UPDATE
A possible solution that is O(n log n) in time and requires O(m) extra space, where m is the number of unique elements in the input array:
template <typename RAIter>
size_t remove_duplicates(RAIter first, RAIter last) {
using value_type = typename std::iterator_traits<RAIter>::value_type;
std::map<value_type, size_t> map;
size_t n = 0;
for (auto it = first; it != last; ++it) {
auto & temp = map[*it];
if (temp == 0) temp = ++n;
}
for (auto & e : map)
*(first + e.second - 1) = e.first;
return n;
}
Note also that the contents of the original array is destroyed here, but this is in your attempt as well.
Possible usage:
int main() {
static constexpr size_t n = 26;
std::array<int, n> a = { 0, 0, 1, 0, 3, 2, 1, 1, 0, 1, 0, 0, 2, 2, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1 };
size_t m = remove_duplicates(std::begin(a), std::end(a));
for (size_t i = 0; i < m; i++)
std::cout << a[i] << " ";
std::cout << std::endl;
}
Which prints out 0 1 3 2.
I compared my solution with yours (corrected by #Onk_r). For an input array of 500,000 elements having random values from [0,100). My O(n log n) solution took 19 milliseconds, while your O(n3) solution took 54 seconds! Nice demonstration of how much complexity matters :).
It works, but you have to start with j=1, not 0
wrong:
for (int i=0; i < n; i++){
for(int j=0;j<=i;j++)
solution:
for (int i=0; i < n; i++){
for(int j=1;j<=i;j++){
int arr1[] = {3, 1, 5, 4, 5, 1, 9, 3, 9, 7};
int size = sizeof(arr1) / sizeof(arr1[0]);
int i, j, k = 0;
int arr2[size];
for(i = 0; i < size; i++)
{
for(j = 0; j < k; j++)
{
if(arr1[i] == arr2[j])
{
break;
}
}
if(j == k)
{
arr2[k++] = arr1[i];
}
}
Use a set instead since all elements in a set must be unique. http://www.cplusplus.com/reference/set/set/

MPI_scatter: Invalid buffer pointer

Can anybody tell what am I doing wrong due to which I am getting this error.
Code:
#include<stdio.h>
#include<mpi.h>
void transpose(int ** p, int row, int col)
{
int ** tempVar;
tempVar = (int *)malloc(sizeof(int *)* row);
int i = 0;
for (; i < row; i++)
{
tempVar[i] = (int *)malloc(sizeof (int *)* col);
int j = 0;
while (j < col)
{
tempVar[i][j] = p[j][i];
j++;
}
}
p = tempVar;
}
void main(int argc, char * argv[])
{
int rank, size;
MPI_Init(argc, argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int d[] = { 1000, 1000, 1000, 1000, 1000, 1000 };
int vt[6] = { 1000, 1000, 1000, 1000, 1000, 1000 };
int ** p;
p = (int *)malloc(sizeof(int *)* 6);
int i = 0;
int row = 6;
int col = 6;
while (i < 6)
{
p[i] = (int *)malloc(sizeof(int *)* 6);
/*int j = 0;
if (rank == 0)
{
while (j < 6)
{
scanf("%d", p[i][j]);
j++;
}
}*/
i++;
}
p[0][0] = 0; p[0][1] =2 ; p[0][2] =3 ; p[0][3] =1 ; p[0][4] =1000 ; p[0][5] =1000 ;
p[1][0] = 2; p[1][1] = 0; p[1][2] = 1000; p[1][3] = 1000; p[1][4] = 5; p[1][5] = 1000;
p[2][0] = 3; p[2][1] = 1000; p[2][2] = 0; p[2][3] = 1000; p[2][4] = 1000; p[2][5] = 1;
p[3][0] = 1; p[3][1] = 1000; p[3][2] = 1000; p[3][3] = 0; p[3][4] = 4; p[3][5] = 3;
p[4][0] = 1000; p[4][1] = 5; p[4][2] = 1000; p[4][3] = 4; p[4][4] = 0; p[4][5] = 2;
p[5][0] = 1000; p[5][1] = 1000; p[5][2] = 1; p[5][3] = 3; p[5][4] = 2; p[5][5] = 0;
int smallest;
if (rank == 0)
{
//transpose(&p , row , col);
smallest = 0;
vt[smallest] = smallest;
//MPI_Bcast();
}
int vt1, d1;
vt1 = d1 = 0;
int roww[6];
MPI_Scatter(vt, 6, MPI_INT, vt1, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(d, 6, MPI_INT, d1, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(p, row *row, MPI_INT,roww, 6, MPI_INT, 0, MPI_COMM_WORLD);
i = 0;
while (i < (row*row)/size)
{
MPI_Bcast(smallest, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (vt1 != rank)
{
if (roww[smallest] != 1000)
{
if (d1 > roww[smallest])
d1 = roww[smallest];
}
}
MPI_Gather(d1, 1, MPI_INT, d, row, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0)
{
smallest = d[0];
int k = 1;
int index = 0;
while (k < 6)
{
if (d[k] < smallest)
{
smallest = d[k];
index = k;
}
k++;
}
vt[k] = index;
}
MPI_Scatter(vt, 6, MPI_INT, vt1, (row) / size, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(d, 6, MPI_INT, d1, (row) / size, MPI_INT, 0, MPI_COMM_WORLD);
i++;
}
MPI_Finalize();
}
The error that I am getting is
Fatal Error: fatal error in MPI_Scatter: Invalid buffer pointer, error stack:
MPI_Scatter(760): MPI_Scatter(sbuf=0x0085f7ac , scount , MPI_INT , rbuf =0x0000000 , rcount =1, MPI_INT , root= 0 , MPI_COMM_WORLD) failed
The code you provided compiles with lots of warnings that are not to be ignored such as :
passing argument 2 of ‘MPI_Init’ from incompatible pointer type
Look carefully at the prototype of functions : int* fun(int* b); is likely to fail if you call something like int d;fun(d);. If the function needs a pointer to the data, fun(&d) may work better. This problem occurs many times, as MPI functions are called.
More : the function transpose(int ** p) tries to modify p by doing p= tempVar. As signaled by #WhozCraig, by doing int **p;...;transpose(p,...), a copy of p in the scope of the function transpose() is modified, but not p. Hence, the right prototype of this function is transpose(int ***p,...) and the right way to call it is int** p;...;transpose(&p,...);
Regarding memory allocation : you found a way to allocate 2D array ! But the data is not contiguous in memory since rows are allocated one at a time. If you plan to use MPI functions such as MPI_Scatter(), allocating a contiguous 2D array is the right way to go (more).
Additional advice : call free() at the right time to free the memory and avoid memory leaks. Do not cast the return of malloc()
Here is a piece of code that should compile well with mpicc main.c -o main -Wall. The option -Wall enables all warnings. It seems to run fine, though i did not check if the result is correct.
#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
void transpose(int *** p, int row, int col)
{
int ** tempVar;
tempVar = malloc(sizeof(int *)* row);
if (tempVar==NULL){printf("malloc failed\n"); exit (1);}
tempVar[0] = malloc(sizeof (int )* col*row);
if (tempVar[0]==NULL){printf("malloc failed\n"); exit (1);}
int i = 0;
for (i=0; i < row; i++)
{
tempVar[i] = &tempVar[0][col*i];
int j = 0;
while (j < col)
{
tempVar[i][j] = (*p)[j][i];
j++;
}
}
free((*p)[0]);
free(*p);
*p = tempVar;
}
int main(int argc, char * argv[])
{
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int d[] = { 1000, 1000, 1000, 1000, 1000, 1000 };
int vt[6] = { 1000, 1000, 1000, 1000, 1000, 1000 };
int ** p;
int i = 0;
int row = 6;
int col = 6;
p = malloc(sizeof(int *)* row);
if (p==NULL){printf("malloc failed\n"); exit (1);}
p[0] = malloc(sizeof(int )* row*col);
if (p[0]==NULL) {printf("malloc failed\n"); exit (1);}
while (i < row)
{
p[i] = &p[0][i*col];
/*int j = 0;
if (rank == 0)
{
while (j < 6)
{
scanf("%d", p[i][j]);
j++;
}
}*/
i++;
}
p[0][0] = 0; p[0][1] =2 ; p[0][2] =3 ; p[0][3] =1 ; p[0][4] =1000 ; p[0][5] =1000 ;
p[1][0] = 2; p[1][1] = 0; p[1][2] = 1000; p[1][3] = 1000; p[1][4] = 5; p[1][5] = 1000;
p[2][0] = 3; p[2][1] = 1000; p[2][2] = 0; p[2][3] = 1000; p[2][4] = 1000; p[2][5] = 1;
p[3][0] = 1; p[3][1] = 1000; p[3][2] = 1000; p[3][3] = 0; p[3][4] = 4; p[3][5] = 3;
p[4][0] = 1000; p[4][1] = 5; p[4][2] = 1000; p[4][3] = 4; p[4][4] = 0; p[4][5] = 2;
p[5][0] = 1000; p[5][1] = 1000; p[5][2] = 1; p[5][3] = 3; p[5][4] = 2; p[5][5] = 0;
int smallest;
if (rank == 0)
{
//transpose(&p , row , col);
smallest = 0;
vt[smallest] = smallest;
//MPI_Bcast();
}
int vt1, d1;
vt1 = d1 = 0;
int roww[col];
MPI_Scatter(vt, 1, MPI_INT, &vt1, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(d, 1, MPI_INT, &d1, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(&p[0][0], col, MPI_INT,roww, col, MPI_INT, 0, MPI_COMM_WORLD);
i = 0;
while (i < (row*row)/size)
{
MPI_Bcast(&smallest, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (vt1 != rank)
{
if (roww[smallest] != 1000)
{
if (d1 > roww[smallest])
d1 = roww[smallest];
}
}
MPI_Gather(&d1, 1, MPI_INT, d, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0)
{
smallest = d[0];
int k = 1;
int index = 0;
while (k < 6)
{
if (d[k] < smallest)
{
smallest = d[k];
index = k;
}
k++;
}
vt[k] = index;
}
MPI_Scatter(vt, 1, MPI_INT, &vt1, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Scatter(d, 1, MPI_INT, &d1, 1, MPI_INT, 0, MPI_COMM_WORLD);
i++;
}
free(p[0]);
free(p);
MPI_Finalize();
return 0;
}