I'm a newby in MPI and I'm trying to learn how to use MPI_Type_create_subarray in order to apply it in my projects.
I've spent lots of time searching for a tutorial which could fits my needing, but without success.
So I've tried to generalize the concept in How to use MPI_Type_create_subarray
to 3D arrays, but something is still missing.
In particular my code return a Segmentation Fault error or shows wrong data when I try to see results.
I can't understand where I made a mistake
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void printarr(int ***data, int nx, int ny, int nz, char *str);
int ***allocarray(int nx, int ny, int nz);
int main(int argc, char **argv) {
/* array sizes */
const int bigsize =10;
const int subsize_x =2; const int subsize_y =2; const int subsize_z =2;
/* communications parameters */
const int sender =0;
const int receiver=1;
const int ourtag =2;
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < receiver+1) {
if (rank == 0)
fprintf(stderr,"%s: Needs at least %d processors.\n", argv[0], receiver+1);
MPI_Finalize();
return 1;
}
MPI_Datatype mysubarray;
int starts[3] = {0,0,0};
int subsizes[3] = {subsize_x,subsize_y,subsize_z};
int bigsizes[3] = {bigsize, bigsize, 3};
MPI_Type_create_subarray(3, bigsizes, subsizes, starts, MPI_ORDER_C, MPI_INT, &mysubarray);
MPI_Type_commit(&mysubarray);
if (rank == sender) {
int ***bigarray = allocarray(bigsize,bigsize,3);
for (int k=0; k<3; k++)
for (int j=0; j<bigsize; j++)
for(int i=0; i< bigsize; i++) {
bigarray[k][j][i] = k*(bigsize*bigsize)+j*bigsize+i;
}
printarr(bigarray, bigsize, bigsize, 3, " Sender: Big array ");
MPI_Send(&(bigarray[0][0][0]), 1, mysubarray, receiver, ourtag, MPI_COMM_WORLD);
MPI_Type_free(&mysubarray);
free(bigarray);
} else if (rank == receiver) {
int ***subarray = allocarray(subsize_x,subsize_y,subsize_z);
MPI_Recv(&(subarray[0][0][0]), subsizes[0]*subsizes[1]*subsizes[2], MPI_INT, sender, ourtag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printarr(subarray, subsize_x, subsize_y, subsize_z, " Receiver: Subarray -- after receive");
free(subarray);
}
MPI_Finalize();
return 0;
}
void printarr(int ***data, int nx, int ny, int nz, char *str) {
printf("-- %s --\n", str);
for(int k=0; k<nz; k++) {
printf("\n\n-----%d------\n",k);
for (int j=0; j<ny;j++) {
for (int i=0; i<nx; i++) {
printf("%3d ", data[k][j][i]);
}
printf("\n");
}
}
}
int ***allocarray(int nx, int ny, int nz) {
int*** arr = (int***)malloc(sizeof(int**)*nz);
for(int k = 0; k < nz; k++) {
arr[k]= (int**)malloc(sizeof(int*)*ny);
for(int j = 0; j< ny; j++){
arr[k][j] = (int*)malloc(sizeof(int)*nx);
for(int i = 0; i < nx; i++){
arr[k][j][i] = 0;
}
}
}
return arr;
}
Related
how to output data into new files g1 g2 g3 for each sorting method in c language
This is the code that i have done .. Might be a little messy but i somehow managed to make it work i think. I was wondering how to separately print the sorting output in each of their different files. Any advice or suggestions on how to do it will be appreciated
edit: i dont know if the program works because the plan was to run the loop till the array size (which will be the total values in the file) but i didnt know how to run a loop through an array without knowing its size in c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
void getRandomArray(int arr[], int n, int max); //initiate an array with random numbers
void cloneArray(int arrB[], int arrA[], int size); //copy an array to another
void printArray(int arr[], int size); //print all elements of an array
void swap(int *xp, int *yp);
void selectionSort(int arr[], int n); //selection sort
void insertionSort(int list[], int n); //insertion sort
int main(int argc, char *argv[]) {
FILE *myFile;
myFile = fopen("test_dat.txt", "r");
//read file into array
int i;
int SIZE=10000;
int arrA[SIZE], arrB[SIZE];
if (myFile == NULL){
printf("Error Reading File\n");
exit (0);
}
for (i = 0; i <SIZE; i++){
fscanf(myFile, "%d,", &arrA[i] );
}
cloneArray( arrB, arrA, SIZE);
printArray(arrA, SIZE);
clock_t start = clock();
cloneArray(arrB, arrA, SIZE);
start = clock();
selectionSort(arrB, SIZE);
printf("Time = %f ms\n", 1000.0*(clock()-start)/CLOCKS_PER_SEC);
printArray(arrB, SIZE);
cloneArray(arrB, arrA, SIZE);
start = clock();
insertionSort(arrB, SIZE);
printf("Time = %f ms\n", 1000.0*(clock()-start)/CLOCKS_PER_SEC);
printArray(arrB, SIZE);
free(arrA);
free(arrB);
fclose(myFile);
}
//=======================================================
void cloneArray(int arrB[], int arrA[], int size) {
for (int i = 0; i < size; i++)
arrB[i] = arrA[i];
}
void printArray(int arr[], int size) {
for (int i=0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
//=======================================================
void selectionSort(int arr[], int n) {
puts("\n==================== Selection Sort ==================== ");
int comp = 0, swp = 0;
int min_idx;
for (int i = 0; i < n-1; i++) {
min_idx = i;
for (int j = i+1; j < n; j++)
if (arr[j] < arr[min_idx]) {
min_idx = j;
comp++;
}
swap(&arr[min_idx], &arr[i]);
swp++;
}
printf("No. comparisons = %d; No. swaps = %d\n", comp, swp);
}
void insertionSort(int list[], int n) {
puts("\n==================== Insertion Sort ====================");
int comp = 0, assg = 0;
for (int h = 1; h < n; h++) {
int key = list[h];
int k = h - 1; //start comparing with previous item
while (k >= 0 && key < list[k]) {
list[k + 1] = list[k];
comp++;
assg++;
--k;
}
list[k + 1] = key;
}
printf("No. comparisons = %d; No. assignments = %d\n", comp, assg);
return 0;
} //end insertionSort
I got the above mentioned error on running the following program in C.
This program Firstly generates 3x3 array and executes Jacobi iteration. It uses MPI library. I don't know what parts of code are wrong.:
#include <stdio.h>
#include <string.h>
#include <mpi.h>
#include <math.h> // l2-norm //
#include <time.h>
int main(int argc, char **argv)
{
int numprocs, myid;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
double a[3][3];
double b[3];
double x[3]={0};
double xa[3]={0};
double xnew[3]={0};
double y[3]={0};
float sigancha;
time_t startTime=0, endTime=0;
int n=3;
int i, j =0;
int k=0;
int o;
int hoessu=300;
int minhoessu=300;
double sum=1;
int numsent =0;
int ans;
int row;
MPI_Status status;
int sender;
int po;
double *buffer;
/* synchronization */
MPI_Barrier(MPI_COMM_WORLD);
for (i=0; i<n; i++){
b[i]=i*100;
for (j=0; j<n; j++) {
a[i][j]=((i+j)%10);
if (i==j) {a[i][j]+=5000;}
}
x[i]=b[i]/a[i][i];
}
/* run if sum is greater than 0.0002 */
for (k=0; k<hoessu&&sum>0.0002||k<minhoessu; k++) {
numsent = 0;
for (o=myid+1; o<n+1; o+=numprocs) {
i=o-1;
xa[i]=b[i]+a[i][i]*x[i];
for (j=0; j<n; j++) {
xa[i]-=a[i][j]*x[j];
}
xnew[i]=xa[i]/a[i][i];
/*send xnew[i] to master*/
MPI_Send(&xnew[i],1,MPI_DOUBLE,0,i,MPI_COMM_WORLD);
}
if (myid == 0){
/*get xnew[i]*/
for (i=0; i<n; i++) {
MPI_Recv(&ans, 1, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
sender = status.MPI_SOURCE;
row = status.MPI_TAG;
xnew[row] = ans;
}
/*calculates sum at master*/
for (j=0; j<n; j++){
sum=0.0;
sum+=(xnew[j]-x[j])*(xnew[j]-x[j]);
x[j]=xnew[j];
}
sum=pow(sum,0.5);
MPI_Bcast(&x[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
}
if (myid == 0){
endTime=clock();
sigancha=(float)(endTime-startTime)/(CLOCKS_PER_SEC);
printf("finished\n");
for (j=0; j<n; j++) {
printf("x[%d]=%fl\n",j+1,xnew[j]);
}
printf("iteration; %d times itereation are done. \n l2-norm, error is %fl .\n %f seceonds are used. \n",k,sum,sigancha);
}
MPI_Finalize();
}
Uses mpicc for compile.
mpicc mpijacobi2.c -o taskingyeje
./taskingyeje
Result.
finished
x[1]=-1736884775.000000l
x[2]=-370936800.000000l
x[3]=2118301216.000000l
iteration; 300 times itereation are done.
l2-norm, error is 34332272.000000l .
0.020000 seceonds are used.
however, this result is not intended result. If this program worked perfectly, It should give same result of serial jacobi iteration.
It would be
x[1]=-0.000020l
x[2]=-0.019968l
x[3]=0.399956l
I don't know why this program generate wrong result.
#include <stdio.h>
#include <string.h>
#include <mpi.h>
#include <math.h> // l2-norm //
#include <time.h>
int main(int argc, char **argv)
{
int numprocs, myid;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
double a[700][700];
double b[700];
double x[700]={0};
double xa[700]={0};
double xnew[700]={0};
double y[700]={0};
float sigancha;
time_t startTime=0, endTime=0;
int n=700;
int i, j =0;
int k=0;
int o;
int hoessu=300;
int minhoessu=300;
double sum=1;
int numsent =0;
int ans;
int row;
MPI_Status status;
int sender;
int po;
double *buffer;
/* synchronization */
MPI_Barrier(MPI_COMM_WORLD);
for (i=0; i<n; i++){
b[i]=i*100;
for (j=0; j<n; j++) {
a[i][j]=((i+j)%10);
if (i==j) {a[i][j]+=10000;}
}
x[i]=b[i]/a[i][i];
}
/* run if sum is greater than 0.0002 */
for (k=0; k<hoessu&&sum>0.0002||k<minhoessu; k++) {
numsent = 0;
for (o=myid+1; o<n+1; o+=numprocs) {
i=o-1;
xa[i]=b[i]+a[i][i]*x[i];
for (j=0; j<n; j++) {
xa[i]-=a[i][j]*x[j];
}
xnew[i]=xa[i]/a[i][i];
/*send xnew[i] to master*/
ans=xnew[i];
MPI_Allgather(&xnew[i],1,MPI_DOUBLE,&xnew[i],1,MPI_DOUBLE,MPI_COMM_WORLD);
}
if (myid == 0){
/*calculates sum at master*/
for (j=0; j<n; j++){
sum=0.0;
sum+=(xnew[j]-x[j])*(xnew[j]-x[j]);
x[j]=xnew[j];
}
sum=pow(sum,0.5);
MPI_Bcast(&x[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
}
}
if (myid == 0){
endTime=clock();
sigancha=(float)(endTime-startTime)/(CLOCKS_PER_SEC);
printf("finished\n");
for (j=0; j<n; j++) {
printf("x[%d]=%fl\n",j+1,xnew[j]);
}
printf("iteration; %d times itereation are done. \n l2-norm, error is %fl .\n %f seceonds are used. \n",k,sum,sigancha);
}
MPI_Finalize();
}
I am trying to implement a map where keys are numbers mapping into unique numbers. In other words, each process holds a set of numbers in an array that map into another set of numbers in another array held by the same process. The mappings need to be unique across all the process. I passed around a struct with the mappings to create mappings for each of the processes. However, this is not parallel, as I sequentially send information through processes. I request help from all of you wonderful programmers of the internet for how all processes can look at a specific variable at the same time? The following is the code I am currently working with. Thanks in advance and for all the support I have received till now.
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct map{ //saves all the mappings
int keys[25];
int values[25];
int grow;
};
struct map rmap; //global map
void mapadd(int key, int value){ //adding values to map
rmap.keys[rmap.grow] = key;
rmap.values[rmap.grow] = value;
rmap.grow++;
}
int mapper(int key){ //get value from key
for(int h=0; h<sizeof(rmap.keys)/sizeof(int); h++){
if(rmap.keys[h] == key){
return rmap.values[h];
}
}
return 0;
}
int finder(int list[], int val, int mem){ //see if a value is in array
for(int l=0; l<mem; l++){
if(list[l] == val){
return 1;
}
}
return 0;
}
int main(int argc, char** argv){
// Initialize the MPI environment
MPI_Init(NULL, NULL);
// Find out rank, size
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
srand(time(0));
rmap.grow = 0;
int dim[world_size];
int maxdim = 0;
for(int s=0; s<world_size; s++){
dim[s] = (rand()%10) + 1;
if(dim[s]>maxdim){
maxdim = dim[s];
}
}
int nums[world_size][maxdim];
int labels[world_size][maxdim];
for(int u=0; u<world_size; u++){
for(int d=0; d<dim[u]; d++){
labels[u][d] = 0;
nums[u][d] = 0;
}
}
for(int t=0; t<world_size; t++){
for(int i=0; i<dim[t]; i++){
nums[t][i] = rand()%26 + 1;
//printf("%d\n", nums[t][i]);
}
}
if(world_rank!=0){
MPI_Recv(&rmap.keys, 25, MPI_INT, world_rank-1, 0,
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Recv(&rmap.values, 25, MPI_INT, world_rank-1, 0,
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
for(int j=0; j<dim[world_rank]; j++){
if(labels[world_rank][j] == 0){
if(finder(rmap.keys, nums[world_rank][j], 25)==1){
//printf("%s", "exist");
labels[world_rank][j] = mapper(nums[world_rank][j]);
}
else{
//printf("%s", "not");
labels[world_rank][j] = (rand()%50) + 1;
mapadd(nums[world_rank][j], labels[world_rank][j]);
/*for(int o=0; o<25; o++){
printf("%d - %d", rmap.keys[o], rmap.values[o]);
}*/
}
}
}
if(world_rank<world_size-1){
MPI_Send(&rmap.keys, 25, MPI_INT, world_rank+1, 0, MPI_COMM_WORLD);
MPI_Send(&rmap.values, 25, MPI_INT, world_rank+1, 0, MPI_COMM_WORLD);
}
for(int rank=0; rank<world_size; rank++){
if(rank==world_rank){
for(int k=0; k<dim[rank]; k++){
printf("Process #%d: %d --> %d\n", rank, nums[rank][k], labels[rank][k]);
}
}
}
MPI_Finalize();
return 0;
}
I feel like I've attempted every combination I know of to get this to work and can't figure it out. How can I scanf() into an int** passed as a pointer to a function? I tried searching but couldn't find this, if it's a duplicate please let me know and I'll delete. It begins to run and after entering a few values it segfaults.
Here's my code, I think it's messing up on the scanf() line of the setMatrix() function:
#include <stdio.h>
#include <stdlib.h>
// create zero initialized matrix
int** callocMatrix(int rmax, int colmax) {
int **mat = calloc(rmax, sizeof(int*));
for(int i = 0; i < rmax; i++) mat[i] = calloc(colmax, sizeof(int));
return mat;
}
// fill matrix
void setMatrix(int ***mat, int r, int c){
printf("Insert the elements of your matrix:\n");
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
printf("Insert element [%d][%d]: ", i, j);
scanf("%d", mat[i][j]); // problem here??
printf("matrix[%d][%d]: %d\n", i, j, (*mat)[i][j]);
}
}
return;
}
// print matrix
void printMatrix(int ***mat, int r, int c){
for (int i=0; i<r;i++){
for (int j=0; j<c;j++) {
printf("%d ", (*mat)[i][j]);
}
printf("\n");
}
}
int main(int argc, char *argv[]) {
int r = 3, c = 3;
int **mat = callocMatrix(r, c);
setMatrix(&mat, r, c);
printMatrix(&mat, r, c);
}
There is no need to use triple pointer ***. Passing two-dimensional array will work as is. Here is the code:
#include <stdio.h>
#include <stdlib.h>
// create zero initialized matrix
int** callocMatrix(int rmax, int colmax) {
int **mat = calloc(rmax, sizeof(int*));
for(int i = 0; i < rmax; i++) mat[i] = calloc(colmax, sizeof(int));
return mat;
}
// fill matrix
void setMatrix(int **mat, int r, int c){
printf("Insert the elements of your matrix:\n");
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
printf("Insert element [%d][%d]: ", i, j);
scanf("%d", &mat[i][j]); // no problem here
printf("matrix[%d][%d]: %d\n", i, j, mat[i][j]);
}
}
}
// print matrix
void printMatrix(int **mat, int r, int c){
for (int i=0; i<r;i++){
for (int j=0; j<c;j++) {
printf("%d ", mat[i][j]);
}
printf("\n");
}
}
int main(int argc, char *argv[]) {
int r = 3, c = 3;
int **mat = callocMatrix(r, c);
setMatrix(mat, r, c);
printMatrix(mat, r, c);
}
Should be:
scanf("%d", &(*mat)[i][j]);
You're passing a pointer to you matrix object, so you need to dereference it (with *) just as you do with printf. scanf then needs the address of the element to write into, so you need the &
I need that vector_total dont have any repeated number.
Function for entry vector1 and vector2 that are declared in main().
void entrada_vectors(int vector1[], int vector2[], int vector_total[], int *n, int *m)
{
int i=0, j=0;
/*Entrarem els nombres del vector 1 primer */
for (i=0; i<*n; i++)
{
vector_total[i]=vector1[i];
}
/*Entrarem els nombres del vector 2 després */
for (i=*n; i<*n+*m; i++)
{
if (j<*m)
{
vector_total[i]=vector2[j];
j++;
}
}
}
Function 2. This is for order numbers in vector_total.
void ordena(int vector_total[], int *n, int *m)
{
int i=0, j=0;
int aux=0;
for (i=0; i<*n+*m-1; i++)
{
for (j=0; j<*n+*m-1; j++)
{
if (vector_total[j]>vector_total[j+1])
{
aux=vector_total[j];
vector_total[j]=vector_total[j+1];
vector_total[j+1]=aux;
aux=0;
}
}
}
}
Function 3. Print vector_total
void mostra(int vector_total[], int *n, int *m )
{ int i;
for (i=0; i<*n+*m; i++)
{
printf ("Pos %d del vector: %d\n", i, vector_total[i] );
}
}
Function 4. Here are the problem!! This function is for clean my vector_total and drop the repeated numbers.
void limpiar_repetidos(int vector_total[], int *n, int *m)
{
int x=0, i=0, j=0;
for (i=0; i<*n+*m-1; i++)
{
for (j=0; j<*n+*m-1; j++)
{
if (vector_total[j]==vector_total[j+1])
{
x=j+1;
for (i=*n+*m; i>x; i--)
{
vector_total[i-1]=vector_total[i];
}
}
}
}
}
And here is my main. And my declaration variables:
int vector1[]={7,1,5,3,4,2};
int vector2[]={3,7,3,0,9,10};
int n=sizeof(vector1)/sizeof(vector1[0]);
int m=sizeof(vector2)/sizeof(vector2[0]);
int vector_total[n+m];
main()
{
entrada_vectors(vector1, vector2, vector_total, &n, &m);
ordena(vector_total, &n, &m);
mostra(vector_total, &n, &m);
limpiar_repetidos(vector_total, &n, &m);
printf ("==================\n");
mostra(vector_total, &n, &m);
return 0;
}
Thanks everybody! :)
1) If function deal with only a vector_total , Length of the vector_total is better to pass by one argument. Also you do not need to pointer pass if it will not change.
void mostra(int vector_total[], int len){
int i;
for (i=0; i<len; i++) {
printf ("Pos %d del vector: %d\n", i, vector_total[i] );
}
}
2) function need a new length after the element has been removed. Also, deletion of adjacent same elements that can be like this.
int limpiar_repetidos(int vector_total[], int len){//int *n, int *m --> int len
int i, size, new_size;
size = len;
for(i = new_size = 1; i < size; ++i){
if(vector_total[new_size-1] != vector_total[i])
vector_total[new_size++] = vector_total[i];
}
return new_size;
}
Example of use
mostra(vector_total, m + n);
int l = limpiar_repetidos(vector_total, n + m);
mostra(vector_total, l);