#include<stdio.h>
#include<mpi.h>
#include<stdlib.h>
#include<math.h>
#define N 8
#define MASTER 0
#define DEFAULT_TAG 0
//za N = 8 program se startuje za 16 procesa
//za N = 4 program se startuje za 4 procesa
void printMatrix(int* mat, int rows, int cols, const char* msg);
void printVector(int arr[], int len, const char* msg);
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 a[N][N], b[N], c[N];
const int q
= (int)sqrt(size
), // q predstavlja red velicine matrice procesa l = N / q,// l predstavlja broj redova u podmatrici A kao i broj elemenata podvektora B
k = q + 1; // k predstavlja broj kolona u podmatrici A
int* locA
= calloc(l
* k
, sizeof(int)), * locB
= calloc(l
, sizeof(int)), * tmp
= calloc(l
, sizeof(int)), * rowsTmp
= calloc(l
, sizeof(int));
MPI_Datatype submatrixType;
MPI_Type_vector(l, k, N, MPI_INT, &submatrixType);
MPI_Type_commit(&submatrixType);
if (rank == MASTER) {
int cnt = 0;
for (int i = 0; i < N; i++) {
b[i] = i;
for (int j = 0; j < N; j++)
a[i][j] = cnt++;
}
printMatrix(&a[0][0], N, N, "\nMatrica A:\n");
printVector(b, N, "Vektor B: ");
int proc = 0;
for (int i = 0; i < q; i++)
for (int j = 0; j < q; j++) {
if (proc == MASTER) {
for (int i = 0; i < l; i++)
for (int j = 0; j < k; j++)
locA[i * k + j] = a[i][j];
proc++;
}
else
MPI_Send(&a[i * l][j], 1, submatrixType, proc++, DEFAULT_TAG, MPI_COMM_WORLD);
}
}
else
MPI_Recv(locA, l * k, MPI_INT, MASTER, DEFAULT_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Datatype subvectorType, resizedSubvectorType;
MPI_Type_vector(l, 1, q, MPI_INT, &subvectorType);
MPI_Type_create_resized(subvectorType, 0, 1 * sizeof(int), &resizedSubvectorType);
MPI_Type_commit(&resizedSubvectorType);
MPI_Comm rowsComm, colsComm;
MPI_Comm_split(MPI_COMM_WORLD, rank / q, rank % q, &rowsComm);
MPI_Comm_split(MPI_COMM_WORLD, rank % q, rank / q, &colsComm);
int rowsRank, colsRank;
MPI_Comm_rank(rowsComm, &rowsRank);
MPI_Comm_rank(colsComm, &colsRank);
if (colsRank == MASTER)
MPI_Scatter(&b, 1, resizedSubvectorType, locB, l, MPI_INT, MASTER, rowsComm);
MPI_Bcast(locB, l, MPI_INT, MASTER, colsComm);
struct {
int val;
int rank;
} locMin = { INT32_MAX, rank }, min = { INT32_MAX, -1 };
for (int i = 0; i < l; i++)
for (int j = 0; j < k; j++)
if (locMin.val > locA[i * k + j])
locMin.val = locA[i * k + j];
MPI_Reduce(&locMin, &min, 1, MPI_2INT, MPI_MINLOC, MASTER, MPI_COMM_WORLD);
MPI_Bcast(&min, 1, MPI_2INT, MASTER, MPI_COMM_WORLD);
//Mnoze se samo elementi nulte i poslednje kolone iz locA sa elementima iz locB
for (int i = 0; i < l; i++)
for (int j = 0; j < l; j++) {
tmp[i] += locA[i * k + j * (k - 1)] * locB[j]; //Nacrtaj si
}
//U nultoj koloni matrice procesa su svi medjurezultati
MPI_Reduce(tmp, rowsTmp, l, MPI_INT, MPI_SUM, MASTER, rowsComm);
//skupljamo u master proces nulte kolone koji je i globalni.
if (rowsRank == MASTER)
MPI_Gather(rowsTmp, l, MPI_INT, &c[0], l, MPI_INT, min.rank, colsComm);
printf("\n[Process %d]-----------------------\n", rank
); printMatrix(locA, l, k, "locA:\n");
printVector(locB, l, "locB: ");
if (rank == min.rank) {
printf("Ja, proces %d, sadrzim najmanji element matrice A.\n", rank
); printVector(c, N, "Rezultujuci vektor C: ");
}
MPI_Finalize();
return 0;
}
void printMatrix(int* mat, int rows, int cols, const char* msg) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++)
printf("%d\t", mat
[i
* cols
+ j
]); }
}
void printVector(int arr[], int len, const char* msg) {
for (int i = 0; i < len; i++)
printf(i
< len
- 1 ? "%d, " : "%d]", arr
[i
]); }
I2luY2x1ZGU8c3RkaW8uaD4KI2luY2x1ZGU8bXBpLmg+CiNpbmNsdWRlPHN0ZGxpYi5oPgojaW5jbHVkZTxtYXRoLmg+CiNkZWZpbmUgTiA4CiNkZWZpbmUgTUFTVEVSIDAKI2RlZmluZSBERUZBVUxUX1RBRyAwCgovL3phIE4gPSA4IHByb2dyYW0gc2Ugc3RhcnR1amUgemEgMTYgcHJvY2VzYQovL3phIE4gPSA0IHByb2dyYW0gc2Ugc3RhcnR1amUgemEgNCBwcm9jZXNhCgp2b2lkIHByaW50TWF0cml4KGludCogbWF0LCBpbnQgcm93cywgaW50IGNvbHMsIGNvbnN0IGNoYXIqIG1zZyk7CnZvaWQgcHJpbnRWZWN0b3IoaW50IGFycltdLCBpbnQgbGVuLCBjb25zdCBjaGFyKiBtc2cpOwoKaW50IG1haW4oaW50IGFyZ2MsIGNoYXIqKiBhcmd2KSB7CglpbnQgcmFuaywgc2l6ZTsKCglNUElfSW5pdCgmYXJnYywgJmFyZ3YpOwoJTVBJX0NvbW1fcmFuayhNUElfQ09NTV9XT1JMRCwgJnJhbmspOwoJTVBJX0NvbW1fc2l6ZShNUElfQ09NTV9XT1JMRCwgJnNpemUpOwoKCWludCBhW05dW05dLCBiW05dLCBjW05dOwoJY29uc3QgaW50IHEgPSAoaW50KXNxcnQoc2l6ZSksIC8vIHEgcHJlZHN0YXZsamEgcmVkIHZlbGljaW5lIG1hdHJpY2UgcHJvY2VzYQoJCWwgPSBOIC8gcSwvLyBsIHByZWRzdGF2bGphIGJyb2ogcmVkb3ZhIHUgcG9kbWF0cmljaSBBIGthbyBpIGJyb2ogZWxlbWVuYXRhIHBvZHZla3RvcmEgQgoJCWsgPSBxICsgMTsgLy8gayBwcmVkc3RhdmxqYSBicm9qIGtvbG9uYSB1IHBvZG1hdHJpY2kgQQoKCWludCogbG9jQSA9IGNhbGxvYyhsICogaywgc2l6ZW9mKGludCkpLAoJCSogbG9jQiA9IGNhbGxvYyhsLCBzaXplb2YoaW50KSksCgkJKiB0bXAgPSBjYWxsb2MobCwgc2l6ZW9mKGludCkpLAoJCSogcm93c1RtcCA9IGNhbGxvYyhsLCBzaXplb2YoaW50KSk7CgoJTVBJX0RhdGF0eXBlIHN1Ym1hdHJpeFR5cGU7CglNUElfVHlwZV92ZWN0b3IobCwgaywgTiwgTVBJX0lOVCwgJnN1Ym1hdHJpeFR5cGUpOwoJTVBJX1R5cGVfY29tbWl0KCZzdWJtYXRyaXhUeXBlKTsKCglpZiAocmFuayA9PSBNQVNURVIpIHsKCQlpbnQgY250ID0gMDsKCQlmb3IgKGludCBpID0gMDsgaSA8IE47IGkrKykgewoJCQliW2ldID0gaTsKCQkJZm9yIChpbnQgaiA9IDA7IGogPCBOOyBqKyspCgkJCQlhW2ldW2pdID0gY250Kys7CgkJfQoKCQlwcmludE1hdHJpeCgmYVswXVswXSwgTiwgTiwgIlxuTWF0cmljYSBBOlxuIik7CgkJcHJpbnRWZWN0b3IoYiwgTiwgIlZla3RvciBCOiAiKTsKCgkJaW50IHByb2MgPSAwOwoJCWZvciAoaW50IGkgPSAwOyBpIDwgcTsgaSsrKQoJCQlmb3IgKGludCBqID0gMDsgaiA8IHE7IGorKykgewoJCQkJaWYgKHByb2MgPT0gTUFTVEVSKSB7CgkJCQkJZm9yIChpbnQgaSA9IDA7IGkgPCBsOyBpKyspCgkJCQkJCWZvciAoaW50IGogPSAwOyBqIDwgazsgaisrKQoJCQkJCQkJbG9jQVtpICogayArIGpdID0gYVtpXVtqXTsKCQkJCQlwcm9jKys7CgkJCQl9CgkJCQllbHNlCgkJCQkJTVBJX1NlbmQoJmFbaSAqIGxdW2pdLCAxLCBzdWJtYXRyaXhUeXBlLCBwcm9jKyssIERFRkFVTFRfVEFHLCBNUElfQ09NTV9XT1JMRCk7CgkJCX0KCX0KCWVsc2UKCQlNUElfUmVjdihsb2NBLCBsICogaywgTVBJX0lOVCwgTUFTVEVSLCBERUZBVUxUX1RBRywgTVBJX0NPTU1fV09STEQsIE1QSV9TVEFUVVNfSUdOT1JFKTsKCglNUElfRGF0YXR5cGUgc3VidmVjdG9yVHlwZSwgcmVzaXplZFN1YnZlY3RvclR5cGU7CglNUElfVHlwZV92ZWN0b3IobCwgMSwgcSwgTVBJX0lOVCwgJnN1YnZlY3RvclR5cGUpOwoJTVBJX1R5cGVfY3JlYXRlX3Jlc2l6ZWQoc3VidmVjdG9yVHlwZSwgMCwgMSAqIHNpemVvZihpbnQpLCAmcmVzaXplZFN1YnZlY3RvclR5cGUpOwoJTVBJX1R5cGVfY29tbWl0KCZyZXNpemVkU3VidmVjdG9yVHlwZSk7CgoJTVBJX0NvbW0gcm93c0NvbW0sIGNvbHNDb21tOwoJTVBJX0NvbW1fc3BsaXQoTVBJX0NPTU1fV09STEQsIHJhbmsgLyBxLCByYW5rICUgcSwgJnJvd3NDb21tKTsKCU1QSV9Db21tX3NwbGl0KE1QSV9DT01NX1dPUkxELCByYW5rICUgcSwgcmFuayAvIHEsICZjb2xzQ29tbSk7CgoJaW50IHJvd3NSYW5rLCBjb2xzUmFuazsKCU1QSV9Db21tX3Jhbmsocm93c0NvbW0sICZyb3dzUmFuayk7CglNUElfQ29tbV9yYW5rKGNvbHNDb21tLCAmY29sc1JhbmspOwoKCWlmIChjb2xzUmFuayA9PSBNQVNURVIpCgkJTVBJX1NjYXR0ZXIoJmIsIDEsIHJlc2l6ZWRTdWJ2ZWN0b3JUeXBlLCBsb2NCLCBsLCBNUElfSU5ULCBNQVNURVIsIHJvd3NDb21tKTsKCU1QSV9CY2FzdChsb2NCLCBsLCBNUElfSU5ULCBNQVNURVIsIGNvbHNDb21tKTsKCglzdHJ1Y3QgewoJCWludCB2YWw7CgkJaW50IHJhbms7Cgl9IGxvY01pbiA9IHsgSU5UMzJfTUFYLCByYW5rIH0sIG1pbiA9IHsgSU5UMzJfTUFYLCAtMSB9OwoKCWZvciAoaW50IGkgPSAwOyBpIDwgbDsgaSsrKQoJCWZvciAoaW50IGogPSAwOyBqIDwgazsgaisrKQoJCQlpZiAobG9jTWluLnZhbCA+IGxvY0FbaSAqIGsgKyBqXSkKCQkJCWxvY01pbi52YWwgPSBsb2NBW2kgKiBrICsgal07CgoJTVBJX1JlZHVjZSgmbG9jTWluLCAmbWluLCAxLCBNUElfMklOVCwgTVBJX01JTkxPQywgTUFTVEVSLCBNUElfQ09NTV9XT1JMRCk7CglNUElfQmNhc3QoJm1pbiwgMSwgTVBJXzJJTlQsIE1BU1RFUiwgTVBJX0NPTU1fV09STEQpOwoKCS8vTW5vemUgc2Ugc2FtbyBlbGVtZW50aSBudWx0ZSBpIHBvc2xlZG5qZSBrb2xvbmUgaXogbG9jQSBzYSBlbGVtZW50aW1hIGl6IGxvY0IKCWZvciAoaW50IGkgPSAwOyBpIDwgbDsgaSsrKQoJCWZvciAoaW50IGogPSAwOyBqIDwgbDsgaisrKSB7CgkJCXRtcFtpXSArPSBsb2NBW2kgKiBrICsgaiAqIChrIC0gMSldICogbG9jQltqXTsgLy9OYWNydGFqIHNpCgkJfQoKCS8vVSBudWx0b2oga29sb25pIG1hdHJpY2UgcHJvY2VzYSBzdSBzdmkgbWVkanVyZXp1bHRhdGkKCU1QSV9SZWR1Y2UodG1wLCByb3dzVG1wLCBsLCBNUElfSU5ULCBNUElfU1VNLCBNQVNURVIsIHJvd3NDb21tKTsKCS8vc2t1cGxqYW1vIHUgbWFzdGVyIHByb2NlcyBudWx0ZSBrb2xvbmUga29qaSBqZSBpIGdsb2JhbG5pLgoJaWYgKHJvd3NSYW5rID09IE1BU1RFUikKCQlNUElfR2F0aGVyKHJvd3NUbXAsIGwsIE1QSV9JTlQsICZjWzBdLCBsLCBNUElfSU5ULCBtaW4ucmFuaywgY29sc0NvbW0pOwoKCXByaW50ZigiXG5bUHJvY2VzcyAlZF0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuIiwgcmFuayk7CglwcmludE1hdHJpeChsb2NBLCBsLCBrLCAibG9jQTpcbiIpOwoJcHJpbnRWZWN0b3IobG9jQiwgbCwgImxvY0I6ICIpOwoKCWlmIChyYW5rID09IG1pbi5yYW5rKSB7CgkJcHJpbnRmKCJKYSwgcHJvY2VzICVkLCBzYWRyemltIG5ham1hbmppIGVsZW1lbnQgbWF0cmljZSBBLlxuIiwgcmFuayk7CgkJcHJpbnRWZWN0b3IoYywgTiwgIlJlenVsdHVqdWNpIHZla3RvciBDOiAiKTsKCX0KCglmcmVlKGxvY0EpOwoJZnJlZShsb2NCKTsKCWZyZWUodG1wKTsKCWZyZWUocm93c1RtcCk7CgoJTVBJX0ZpbmFsaXplKCk7CglyZXR1cm4gMDsKfQoKdm9pZCBwcmludE1hdHJpeChpbnQqIG1hdCwgaW50IHJvd3MsIGludCBjb2xzLCBjb25zdCBjaGFyKiBtc2cpIHsKCW1zZyYmIHByaW50Zihtc2cpOwoKCWZvciAoaW50IGkgPSAwOyBpIDwgcm93czsgaSsrKSB7CgkJZm9yIChpbnQgaiA9IDA7IGogPCBjb2xzOyBqKyspCgkJCXByaW50ZigiJWRcdCIsIG1hdFtpICogY29scyArIGpdKTsKCQlwcmludGYoIlxuIik7Cgl9Cn0KCnZvaWQgcHJpbnRWZWN0b3IoaW50IGFycltdLCBpbnQgbGVuLCBjb25zdCBjaGFyKiBtc2cpIHsKCW1zZyYmIHByaW50Zihtc2cpOwoKCXByaW50ZigiWyIpOwoJZm9yIChpbnQgaSA9IDA7IGkgPCBsZW47IGkrKykKCQlwcmludGYoaSA8IGxlbiAtIDEgPyAiJWQsICIgOiAiJWRdIiwgYXJyW2ldKTsKCXByaW50ZigiXG4iKTsKfQoK