C code counting occurrences in Matrix using sub matrices and MPI Parallelization - c

I have an assignment to take in a 16 by 16 array of random numbers between 0-31 from a text file. I have been able to read in the matrix and allocate it to a 2D array called arr1. Now I need to use MPI to make my code work when parallelized over 1,4,8,16,32 cores per processor. Can someone show me how to weave in the MPI calls to split up the large matrix into varying sizes of submatrices depending on number of processors? Then use MPI to send, receive, etc. I want each node to count the occurrences of its sub matrix and the root node to combine them all and print out final tally.
//#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int MAXR,MAXC;
MAXR= 16; MAXC=16;
int arr1[MAXR][MAXC],i,j;
FILE *fp;
fp =fopen("arrays16.txt","r");
for(i=0;i<MAXR;i++) // this loop takes the information from .txt file and puts it into arr1 matrix
{
for(j=0;j<MAXC;j++)
{
fscanf(fp,"%d\t",&arr1[i][j]);
}
}
for(i=0;i<MAXR;i++)
{
printf("\n");
for(j=0;j<MAXC;j++)
printf("%d\t",arr1[i][j]);
}
printf("\n\n");
//printf("%d\t",arr1[1][2]);
int occurrences[3][33] = {{0}};
occurrences[0][0] = 0;
occurrences[0][1] = 1;
occurrences[0][2] = 2;
occurrences[0][3] = 3;
occurrences[0][4] = 4;
occurrences[0][5] = 5;
occurrences[0][6] = 6;
occurrences[0][7] = 7;
occurrences[0][8] = 8;
occurrences[0][9] = 9;
occurrences[0][10] = 10;
occurrences[0][11] = 11;
occurrences[0][12] = 12;
occurrences[0][13] = 13;
occurrences[0][14] = 14;
occurrences[0][15] = 15;
occurrences[0][16] = 16;
occurrences[0][17] = 17;
occurrences[0][18] = 18;
occurrences[0][19] = 19;
occurrences[0][20] = 20;
occurrences[0][21] = 21;
occurrences[0][22] = 22;
occurrences[0][23] = 23;
occurrences[0][24] = 24;
occurrences[0][25] = 25;
occurrences[0][26] = 26;
occurrences[0][27] = 27;
occurrences[0][28] = 28;
occurrences[0][29] = 29;
occurrences[0][30] = 30;
occurrences[0][31] = 31;
// for(j=1;j<33;j++)
//{
// printf("%d",occurrences[1][j]);
// }
//printf("\n\n");
int k;
int count;
for(k=0; k <= 31; k++) {
count = 0;
for (i=0; i<= MAXR-1; i++) {
for(j=0;j<=MAXC-1;j++) {
if(arr1[i][j] == occurrences[0][k]) {
count++;
occurrences[1][k] = count;
printf("Occurrences of %d = , are equal to = %d\n",arr1[i][j], occurrences[1][k]);
//break;
}
else {
}
}
}
}
for(i=0;i<1;i++)
{
printf("\n");
for(j=0;j<32;j++)
printf("%d\t",occurrences[i][j]);
}
for(i=1;i<2; i++)
{
printf("\n\n");
for(j=0;j<=32;j++)
printf("%d\t",occurrences[i][j]);
}
}

Related

I am trying to write a simple tsp question but meet some problems

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define max 100
void tsp(int Dis[max][max],int v[],int N,int count,int currPos,int cost,int ans){
/*for(j=1;j<N+1;j++){
if(visited[j]==0){
sum+=Dis[i][j];
visited[j] = 1;
DFS(visited,j,Dis,sum);
}
}*/
if(count == N&&Dis[1][currPos]>0){
if(ans> cost+Dis[1][currPos]) ans = cost+Dis[1][currPos];
//ans = min(ans,cost + Dis[1][currPos]);
return;
}
for (int i = 0;i<N+1;i++){
if(v[i]==0&&Dis[currPos][i]>0){
v[i] = 1;
tsp(Dis,v,N,count + 1,cost + Dis[currPos][i],ans);
v[i] = 0;
}
}
};
int main(int argc, char const *argv[])
{
int N;
int size = 1;
int count = 1;
char x[100] = {0};
FILE *fp=fopen(argv[1],"r");
if(fp==NULL){
printf("Cannot open the file,strike any key to exit!\n");
getchar();
exit(0);
}
for (int i = 0;!feof(fp);i++){
fscanf(fp,"%hhd",&x[i]);
}
N=x[0];
int Dis[N][N], City[N];
for(int i=1;i<N;i++){
size=size*i;
}
char y[size];
for (int i=1;i<size+1;i++){
y[i] = x[i];
//printf("%d\n",y[i]);
}
for(int i=2; i < N + 1; i++){
for(int j=1; j < i ; j++){
Dis[j][i] = y[count];
Dis[i][j] = y[count];
count+=1;
printf("(%d,%d),(%d,%d)",j,i,i,j);
printf("%d\n",Dis[j][i]);
}
}
for(int i=0;i<N;i++){
City[i]=i + 1;//create the number of city with 1 ...... N
}
int curr_constraint = 0;
int v[N+1];
for (int i = 1; i < N+1; i++){
v[i] = 0;
}
for(int i = 1;i<N+1;i++){
curr_constraint += Dis[i][i+1];
}
v[1]= 1;
int ans = INT_MAX;
printf("The orginal constraint is %d\n",curr_constraint);
tsp(Dis[N][N],v,N,0,1,0,ans);
return 0;
}
The question asks me to implement a tsp question which always starts with the number 1 city, it will read the data including the numbers of nodes and length between two citys from a txt file in the position of argv[1]. And then find the smallest way for all city without going back the first city.
The file is like following:
4
5
40 9
11 6 8
which means:
the number of citys N = 4
Distance: d[1][2] = 5, d[1][3] = 40, d[2][3] = 9, d[1][4] = 11, d[2][4] = 6, d[3][4] = 8.
I want to create a array including the distance in tsp function, but the lenght I read only in the main function. How to solve this problem?

Reading Sparse Matrix from Binary File in C

Firstly, I am sorry for my English.
I am trying to read an integer array which represents some sparse matrix from a binary and I have to print this matrix.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
//on this way i have written the matrix in the binary
typedef struct{
int lin,col;
double val;
}termen;
typedef struct{
int nl,nc,nn;
termen* term;
}sparse_matrix;
void afisare_mat(sparse_matrix m){
int i,j,k = 0;
for(i = 0; i < m.nl; i++){
for(j = 0; j < m.nc; j++){
if(i == m.term[k].lin && j == m.term[k].col){
printf("%3.2lf ",m.term[k].val);
k++;
}else{
printf("%d ",0);
}
}printf("\n");
}
}
int main(){
/*this is the code used for write in the binary file
//i tried to print these values and seems to be ok
sparse_matrix m1,m2,m3;
m1.term = malloc(2*sizeof(termen));
m1.nl = 3;
m1.nc = 3;
m1.nn = 2;
m1.term[0].lin = 0;
m1.term[0].col = 1;
m1.term[0].val = 3.2;
m1.term[1].lin = 1;
m1.term[1].col = 2;
m1.term[1].val = 5.6;
afisare_mat(m1);
m2.term = malloc(3*sizeof(termen));
m2.nl = 4;
m2.nc = 4;
m2.nn = 3;
m2.term[0].lin = 0;
m2.term[0].col = 0;
m2.term[0].val = 1.9;
m2.term[1].lin = 1;
m2.term[1].col = 2;
m2.term[1].val = 0.5;
m2.term[2].lin = 2;
m2.term[2].col = 3;
m2.term[2].val = 6.960;
afisare_mat(m2);
m3.term = malloc(1*sizeof(termen));
m3.nl = 3;
m3.nc = 3;
m3.nn = 1;
m3.term[0].lin = 1;
m3.term[0].col = 2;
m3.term[0].val = 6.75;7
afisare_mat(m3);
FILE *f = fopen("in.bin","wb");
fwrite(&m1,sizeof(sparse_matrix),1,f);
fwrite(&m2,sizeof(sparse_matrix),1,f);
fwrite(&m3,sizeof(sparse_matrix),1,f);
fclose(f);
*/
FILE *f = fopen("in.bin","rb");
int n, v[10], i, j, k,nr = 0,it; //n=number of matrix asked, v=array with
//number(s)(<= n) of matrix which have to print
scanf("%d",&n);
sparse_matrix m;
while(fread(&k,sizeof(int),1,f) > 0){
fseek(f,2*sizeof(int),SEEK_CUR);
fseek(f,sizeof(termen*),SEEK_CUR);
nr++;
}
for(i = 0; i < n; i++){
scanf("%d",&v[i]);
if(v[i] > nr)
printf("That matrix not exist\n");
}
fseek(f,0,0);
j = 0;
while(fread(&k,sizeof(int),1,f) > 0){ //citesc nl din fiecare matrice
for(i = 0; i < n; i++){
if(j == v[i]){ //number of matrix which i read;
//print matrix
m.nl = k;
fread(&m.nc,sizeof(int),1,f);
fread(&m.nn,sizeof(int),1,f);
m.term = malloc(m.nn*sizeof(termen));
fread(m.term,sizeof(termen),m.nn,f);
afisare_mat(m);
free(m.term);
fseek(f,(j+1)*sizeof(sparse_matrix),0);
}
}j++;
}
fclose(f);
return 0;
}
This code prints on my screen the form of matrix but full of zeroes. I think that the rest of the elements (!= 0) aren't read ok from the binary file. Can you help me, please?

Loading an Integer Array into a SIMD register

at the moment I'm trying to load an integer array into a SIMD register using SSE.
I have an aligned 32-bit integer array Ai and want to load 4 consecutive elements into a SIMD register Xi. However, the values stored in Xi after executing _mm_load_si128 are garbage except for the first one.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <immintrin.h>
// number has to be divisible by 4 without remainder
#define VECTOR_SIZE 8
int main() {
__attribute__((aligned (16))) int32_t *Ai = (int32_t*) malloc(VECTOR_SIZE * sizeof(int32_t));
for(int i = 0; i < VECTOR_SIZE; i++) {
Ai[i] = rand() % 100000;
}
__m128i Xi;
for(int i = 0; i < VECTOR_SIZE; i+=4) {
Xi = _mm_load_si128((__m128i*) &Ai[i]);
// show content of Xi and Ai
for(int j = 0; j < 4; j++) {
printf("Xi[%d] = %d\t Ai[%d] = %d\n", j, Xi[j], i+j, Ai[i+j]);
}
}
free(Ai);
}
Here is an example output:
Xi[0] = 16807 Ai[0] = 16807
Xi[1] = 50073 Ai[1] = 75249
Xi[2] = 1489217992 Ai[2] = 50073
Xi[3] = 1346391152 Ai[3] = 43658
Xi[0] = 8930 Ai[4] = 8930
Xi[1] = 27544 Ai[5] = 11272
Xi[2] = 1489217992 Ai[6] = 27544
Xi[3] = 1346391168 Ai[7] = 50878
What is wrong?
You probably meant this when you were coming up with your example:
union {
__m128i m128;
int32_t i32[4];
} Xi;
for(int i = 0; i < VECTOR_SIZE; i+=4) {
Xi.m128 = _mm_load_si128((__m128i*) &Ai[i]);
// show content of Xi and Ai
for(int j = 0; j < 4; j++) {
printf("Xi[%d] = %d\t Ai[%d] = %d\n", j, Xi.i32[j], i+j, Ai[i+j]);
}
}
Here is the example output:
Xi[0] = 89383 Ai[0] = 89383
Xi[1] = 30886 Ai[1] = 30886
Xi[2] = 92777 Ai[2] = 92777
Xi[3] = 36915 Ai[3] = 36915
Xi[0] = 47793 Ai[4] = 47793
Xi[1] = 38335 Ai[5] = 38335
Xi[2] = 85386 Ai[6] = 85386
Xi[3] = 60492 Ai[7] = 60492

How to "combine" two int arrays?

Hello i have a little problem trying to "mix" two string arrays, i have searched about it but i have only found how to merge them or concatenate them, but thats not what i need.
i have two int arrays like this:
int no_items = 5;
int parent1[no_items], parent2[no_items];
if the arrays contains for example:
parent1[0] = 1;
parent1[1] = 2;
parent1[2] = 3;
parent1[3] = 4;
parent1[4] = 5;
and:
parent2[0] = 5;
parent2[1] = 1;
parent2[2] = 2;
parent2[3] = 3;
parent2[4] = 4;
given a "cross" point, for example 2:
parent1 should have his 2 first elements and the rest of parent2, and parent2 should have his first 2 elements and the rest of parent1. So the result should be:
parent1: 1,2 | 5,3,4
parent2: 5,1 | 2,3,4
where "|" is the break point index and the rest of elements should not be repeated.
How can i get this kind of mixing two int arrays? Thanks you!
at the moment i have this:
for(i = 0; i < cross_point; i++)
{
sprintf(buffer, "%d,", parent1[i]);
strcat(line1, buffer);
}
for(i = 0; i < cross_point; i++)
{
sprintf(buffer, "%d,", parent2[i]);
strcat(line2, buffer);
}
but i donĀ“t know how to go further than the cross point.
int *find(int *begin, int *end, int value)
{
int *p = begin;
for ( ; p != end; ++p)
if (*p == value) break;
return p;
}
int i, j;
int output1[no_items] = {0};
int output2[no_items] = {0};
int crosspoint = 3;
memcpy(output1, parent1, crosspoint * sizeof(int));
for (i = crosspoint, j = 0; i < no_items; ++i)
{
while (find(output1, output1+i, parent2[j]) != output1+i) ++j;
output1[i] = parent2[j];
}
memcpy(output2, parent2, crosspoint * sizeof(int));
for (i = crosspoint, j = 0; i < no_items; ++i)
{
while (find(output2, output2+i, parent1[j]) != output2+i) ++j;
output2[i] = parent1[j];
}
memcpy(parent1, output1, sizeof(parent1));
memcpy(parent2, output2, sizeof(parent2));
Demo: http://ideone.com/xUt6nQ
something like this should do it if you aren't concerned about creating temporaries:
int no_items = 5;
int output1[no_items];
int output2[no_items];
for (int i = 0; i < no_items; i++){
if(i < crosspoint){
output1[i] = parent1[i];
output2[i] = parent2[i];
}else{
output1[i] = parent2[i];
output2[i] = parent1[i];
}
}
If you are concerned about temporaries you need to swap the values, the logic should be fairly similar to above.
int no_items = 5;
int temp = 0;
for (int i = 0; i < no_items; i++){
if(i < crosspoint){
/* don't need to do anything here */
}else{
temp = parent1[i];
parent1[i] = parent2[i];
parent2[i] = temp;
}
}

Printing 2 dimensional array of pointers to structs

I have been doing homework yesterday, I have done most of it, but couldn't make the main thing. I don't know why it's not working I have asked other students, but nobody knows what's the problem. Basically this program is a small game, there are 18 players 9 on each team. the program randomly gives players coordinates and directions and they start to move. I have basically done the program, but I have problem with field, It doesn't show the players at all.
I tried many things and when testing noticed that it doesn't print even testing string in the if statement I wrote. when I write this part field[i][j] = &players[k][0]; I have checked if field[i][j] really gets the x and y coordinate and yes it does. but in the print_field class it takes field[][] as null and the field is empty. players is an array of structs. field is an array of pointers that point to players or NULL.
I have tried with all of my knowledge and couldn't make any better.
What is wrong with this code? Why isn't it showing the players on the field?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define LENGTH 25
#define WIDTH 25
enum direction {Right, Left, Up, Down}; /*Right = 0, Left = 1, Up = 2, Down = 3*/
void print_field();
void random_positions();
void playerdirection();
void motion();
void game();
struct player
{
char *dora;
char *team;
char *name; //string?
int x,y; //coordinates
int direction;
};
typedef struct player Player;
struct player *field[WIDTH][LENGTH];
Player players[8][1];
int main()
{
srand (time(NULL));
int i; //players 9 in each team team1 = 0 team2 = 1
players[0][0].name = "A1";
players[1][0].name = "A2";
players[2][0].name = "A3";
players[3][0].name = "A4";
players[4][0].name = "A5";
players[5][0].name = "A6";
players[6][0].name = "A7";
players[7][0].name = "A8";
players[8][0].name = "A9";
players[0][1].name = "B1";
players[1][1].name = "B2";
players[2][1].name = "B3";
players[3][1].name = "B4";
players[4][1].name = "B5";
players[5][1].name = "B6";
players[6][1].name = "B7";
players[7][1].name = "B8";
players[8][1].name = "B9";
for(i = 0; i < 9 ; i++)
{
players[i][0].team = "Team A";
players[i][1].team = "Team B";
players[i][0].dora = "Alive";
players[i][1].dora = "Alive";
}
random_positions();
playerdirection();
print_field();
motion (Player player);
print_field();
game();
return 0;
}
void random_positions()
{
int i,j,k;
int xs[17],ys[17];
for(i= 0; i<9 ; i++)
{
players[i][0].x = rand() % 25;
players[i][0].y = rand() % 25;
players[i][1].x = rand() % 25;
players[i][1].y = rand() % 25;
printf("A%d x = %d y = %d \n",i+1,players[i][0].x,players[i][0].y);
printf("B%d x = %d y = %d \n",i+1,players[i][1].x,players[i][1].y);
}
for(i = 0; i < 9 ; i++)
{
xs[i] = players[i][0].x;
xs[i+8] = players[i][1].x;
ys[i] = players[i][0].y;
ys[i+8] = players[i][1].y;
for(j = 0; j <= i ; j++)
{
//printf("j%d start\n",j);
if(i != j && xs[i] == xs[j])
{
//printf("i%d start\n",j);
if(ys[i] == ys[j])
{
return random_positions();
}
//("j%d done\n",j);
}
//printf("j%d done\n",j);
}
}
for(i = 0; i < 25; i++)
{
for(j = 0; j < 25; j++)
{
for(k = 0; k < 9; k++)
{
if(i == players[k][0].x && j == players[k][0].y)
{
field[i][j] = &players[k][0];
}
if(i == players[k][1].x && j == players[k][1].y)
{
field[i][j] = &players[k][1];
}
else field[i][j] = NULL; //I da J sheidzleba shesacvleli iyos
}
}
}
}
/*this function prints out the given state of the field*/
void print_field(){
int i,j;
printf("\n");
printf("|0 1 2 3 4 5 6 7 8 9 101112131415161718192021222324|\n"); /*just to show easier the allignment*/
for(j=0; j<WIDTH+2; j++) /*This first loop goes through row and creates them each by each*/
{
if(j == 0 || j == WIDTH +1) /*creates the upper and lower part of the field*/
for(i=0; i<LENGTH+2; i++) /*there should be space for frame so I added 2 to LENGTH in the loop*/
{
if(i==0)
printf("-");
else if(i == LENGTH+1)
printf("-\n");
else printf("--"); /*3 decimals*/
}
else
for(i=0; i<LENGTH+2; i++) /*Goes through the columns in this row and creates either frame or puts the nodeid*/
{
if(i==0)printf("|"); /*frame*/
else if(i == LENGTH+1) printf("| %d\n",(j-1)); /*frame*/
else if(field[j-1][i-1] != NULL)
{
printf("aaa");
printf("%-*s",2,(*field[j-1][i-1]).name); /*putting nodeid 3 decimals*/
}
else printf(" ");
}
}
printf("\n");
}
You need Player[9][2] instead of Player[8][1]. You should initialize an array with its length although you could only access index up to length - 1 because arrays are indexed from 0.

Resources