Advertisement
Guest User

Untitled

a guest
Apr 8th, 2020
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.43 KB | None | 0 0
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/msg.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <sys/ipc.h>
  8. #include <time.h>
  9.  
  10. double *matrix;
  11. int matrixWidth;
  12. int matrixHeight;
  13. size_t messageSize;
  14. double *vector;
  15. double *results;
  16. int *parentMQIds;
  17.  
  18. void readInput(const char *filename) {
  19.     printf("Reading input starts\n");
  20.     FILE *input = fopen(filename, "r");
  21.     fscanf(input, "%d%d", &matrixWidth, &matrixHeight);
  22.     int matrixSize = matrixWidth * matrixHeight;
  23.     matrix = (double *) calloc(matrixSize, sizeof(double));
  24.     for (int i = 0; i < matrixSize; i += 1)
  25.         fscanf(input, "%lf", (matrix + i));
  26.     vector = (double *) calloc(matrixWidth, sizeof(double));
  27.     for (int i = 0; i < matrixWidth; i += 1)
  28.         fscanf(input, "%lf", (vector + i));
  29.     fclose(input);
  30.     printf("Reading input finishes\n");
  31. }
  32.  
  33. int *distributeRows(int childCount) {
  34.     printf("Distributing rows starts\n");
  35.     int *distribution = (int *) calloc(childCount, sizeof(int));
  36.     int part = matrixHeight / childCount;
  37.     if (part > 0)
  38.         for (int i = 0; i < childCount; i += 1)
  39.             distribution[i] = part;
  40.     int rest = matrixHeight % childCount;
  41.     printf("Rest=%d\n", rest);
  42.     for (int i = rest - 1; i >= 0; i -= 1)
  43.         distribution[i] += 1;
  44.     printf("Distributing rows finishes\n");
  45.     return distribution;
  46. }
  47.  
  48. struct msgbuf {
  49.     long mtype;
  50.     char mtext[10];
  51. };
  52.  
  53. void sendMessage(int parentMQId, double message) {
  54.     struct msgbuf msgbuf;
  55.     char str[10];
  56.     messageSize = sizeof(msgbuf.mtext) + 1;
  57.     sprintf(str, "%lf", message);
  58.     strcpy(msgbuf.mtext, str);
  59.     msgbuf.mtype = 1;
  60.     /* send message to queue */
  61.     if (msgsnd(parentMQId, &msgbuf, messageSize, 0) == -1) {
  62.         if (errno == EAGAIN)
  63.             printf("EAGAIN\n");
  64.         perror("msgsnd");
  65.         exit(1);
  66.     }
  67. }
  68.  
  69. void sendData(int parentMQId, int start, int count) {
  70.     printf("Sending data starts\n");
  71.     sendMessage(parentMQId, matrixWidth);
  72.     //mpStart
  73.     sendMessage(parentMQId, start);
  74.     //rCount
  75.     sendMessage(parentMQId, count);
  76.     /* send vector to queue */
  77.     for (int i = 0; i < matrixWidth; i += 1)
  78.         sendMessage(parentMQId, vector[i]);
  79.     int shift;
  80.     /* send matrix part to queue */
  81.     for (int i = start; i < start + count; i += 1) {
  82.         shift = i * matrixWidth;
  83.         for (int j = 0; j < matrixWidth; j += 1)
  84.             sendMessage(parentMQId, matrix[shift + j]);
  85.     }
  86.     printf("Sending data finishes\n");
  87. }
  88.  
  89. int makeMQ(int proj_id) {
  90.     key_t key = ftok(".", proj_id);
  91.     int parentMQId = msgget(key, 0666 | IPC_CREAT | IPC_EXCL);
  92.     if (parentMQId == -1) {
  93.         if (errno == EEXIST) {
  94.             parentMQId = msgget(key, 0666);
  95.             msgctl(parentMQId, IPC_RMID, NULL);
  96.             parentMQId = msgget(key, 0666 | IPC_CREAT | IPC_EXCL);
  97.             if (parentMQId == -1) {
  98.                 perror("msgget");
  99.                 exit(0);
  100.             }
  101.         } else {
  102.             printf("It is impossible to create message queue\n");
  103.             perror("msgget");
  104.             exit(0);
  105.         }
  106.     }
  107.     return parentMQId;
  108. }
  109.  
  110. int startCalculations(int childCount) {
  111.     int *distribution = distributeRows(childCount);
  112.     printf("Starting up calculation processes starts\n");
  113.     parentMQIds = calloc(childCount, sizeof(int));
  114.     int curStart = 0;
  115.     int i = 0;
  116.     for (i = 0; i < childCount; i += 1) {
  117.         if (distribution[i] == 0)
  118.             break;
  119.         parentMQIds[i] = makeMQ(i);
  120.         printf("Distribution[%d]=%d\n", i, distribution[i]);
  121.         pid_t pid = fork();
  122.         if (pid == -1) {
  123.             perror("fork");
  124.             exit(1);
  125.         }
  126.         if (pid == 0) {
  127.             char str[10];
  128.             sprintf(str, "%d", parentMQIds[i]);
  129.             int res = execl("./calculation.exe", "calculation.exe", str, NULL);
  130.             if (res == -1) {
  131.                 perror("execl");
  132.                 exit(1);
  133.             }
  134.             exit(0);
  135.         }
  136.         sendData(parentMQIds[i], curStart, distribution[i]);
  137.         curStart += distribution[i];
  138.     }
  139.     free(distribution);
  140.     printf("Starting up calculation processes finishes\n");
  141.     return i;
  142. }
  143.  
  144. double receiveMessage(int parentMQId) {
  145.     struct msgbuf msgbuf;
  146.     char *ptr;
  147.     /* receive message from queue */
  148.     if (msgrcv(parentMQId, &msgbuf, messageSize, 2, 0) == -1) {
  149.         perror("main msgrcv");
  150.         exit(1);
  151.     }
  152.     return strtod(msgbuf.mtext, &ptr);
  153. }
  154.  
  155. void receiveResults(int partsToReceive) {
  156.     results = (double *) calloc(matrixWidth, sizeof(double));
  157.     printf("Receiving results starts\n");
  158.     for (int j = 0; j < partsToReceive; j += 1) {
  159.         int startIdx = (int) receiveMessage(parentMQIds[j]);
  160.         int elCount = (int) receiveMessage(parentMQIds[j]);
  161.         /* receive results from queue */
  162.         for (int i = startIdx; i < startIdx + elCount; i += 1) {
  163.             results[i] = receiveMessage(parentMQIds[j]);
  164.         }
  165.         printf("proc %d \n", j);
  166.     }
  167.     printf("Receiving results finishes\n");
  168. }
  169.  
  170. void writeResult(const char *filename) {
  171.     printf("Writing results starts\n");
  172.     FILE *output = fopen(filename, "w");
  173.     for (int i = 0; i < matrixHeight; i += 1)
  174.         fprintf(output, "%.3lf\n", results[i]);
  175.     fclose(output);
  176.     printf("Writing results finishes\n");
  177. }
  178.  
  179. void doCleanup(int partsToReceive) {
  180.     free(matrix);
  181.     free(vector);
  182.     free(results);
  183.     for (int i = 0; i < partsToReceive; i += 1)
  184.         msgctl(parentMQIds[i], IPC_RMID, NULL);
  185.     free(parentMQIds);
  186. }
  187.  
  188. int main(int argc, char *argv[]) {
  189.     if (argc != 2) {
  190.         printf("USAGE: main.exe child_count\n");
  191.         exit(1);
  192.     }
  193.     char *ptr;
  194.     int childCount = (int) strtol(argv[1], &ptr, 10);
  195.     if (childCount <= 0) {
  196.         printf("USAGE: child_count should be more than 0\n");
  197.         exit(1);
  198.     }
  199.     readInput("input.txt");
  200.     clock_t start, end;
  201.     start = clock();
  202.     int partsToReceive = startCalculations(childCount);
  203.     receiveResults(partsToReceive);
  204.     end = clock();
  205.     double diff = difftime(end, start);
  206.     if (diff >= CLOCKS_PER_SEC)
  207.         printf("Calculations have approximately taken %.3lf seconds\n", diff/CLOCKS_PER_SEC);
  208.     else
  209.         printf("Calculations have approximately taken %.3lf milliseconds\n", diff/1000);
  210.     writeResult("output.txt");
  211.     doCleanup(partsToReceive);
  212.     return 0;
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement