Advertisement
Guest User

Untitled

a guest
Feb 25th, 2020
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.70 KB | None | 0 0
  1. #include <sys/ipc.h>
  2. #include <sys/shm.h>
  3. #include <sys/stat.h>
  4. #include <stdlib.h>
  5. #include <stdbool.h>
  6. #include <stdio.h>
  7. #include <errno.h>
  8. #include <math.h>
  9. #include <sys/wait.h>
  10. #include <unistd.h>
  11.  
  12. void errormsg( char *msg ) {
  13. perror( msg );
  14. exit( 1 );
  15. }
  16.  
  17. int sum(int arr[], int m) {
  18. int sum = 0; // initialize sum
  19.  
  20. // Iterate through all elements
  21. // and add them to sum
  22. for (int i = 0; i < m; i++)
  23. sum += arr[i];
  24.  
  25. return sum;
  26. }
  27.  
  28. int main(int argc, char* argv[]) {
  29. int n; // size of input array
  30. int m; // number of processes that will perform the work
  31. char * input_file; // input file name
  32. char * output_file; // output file name
  33.  
  34. int numIter; // Total number of iterations to find the prefix sum output array
  35. int id; // Tracks the id/index each child is responsible for
  36. int pid; // Check if a process is child or parent
  37. int N_MEMORY_SIZE; // Dynamic size to allocate for the N element arrays
  38. int M_MEMORY_SIZE; // Dynamic size to allocate for the M element arrays
  39.  
  40. int * input_arr; // Stores the input nums
  41. int * temp_arr; // Stores the initial array at the beginning of each iteration
  42. int * final_arr; // Stores the final array at the end of each iteration
  43. int * working; // Working array of size m to track the id of each child
  44. int * t; // Used to switch the reference between temp and final arrays at the end of each iteration
  45.  
  46. int tempSId; // temp arrya shared segment id
  47. int finalSId; // final array shared segment id
  48. int workingSId; // working array shared segment id
  49.  
  50. //printf("Finished declaring variables\n");
  51.  
  52. if (argc == 5){
  53. n = atoi(argv[1]); // Read the integer n value
  54. input_file = argv[2]; // Store the input text file name
  55. output_file = argv[3]; // Store the output text file name
  56. m = atoi(argv[4]); // Store the number of processes as an integer
  57.  
  58. } else{
  59. // Number of input parameters does not match
  60. printf("Please enter the correct input values (n input_file output_file m)!\n");
  61. return 1;
  62. }
  63.  
  64. N_MEMORY_SIZE = sizeof(int) * n; // Total size for an array of n int values
  65. M_MEMORY_SIZE = sizeof(int) * m; // Total size for an array of m int values
  66. numIter = ceil(log(n)/log(2)); //correct handle rounding
  67.  
  68. // Initialize the current id to be 0
  69. id = 0;
  70.  
  71. input_arr = (int *)malloc(N_MEMORY_SIZE); // Dynamically create an array to store input values
  72.  
  73. // Create and store the shared segment id for each array
  74.  
  75. tempSId = shmget(IPC_PRIVATE, N_MEMORY_SIZE, S_IRUSR | S_IWUSR); // Create a shared memory segment of size N ints for temp_arr
  76. if ( tempSId < 0 ) errormsg( "ERROR in creating a shared memory segment for TEMP ARRAY\n" );
  77.  
  78. finalSId = shmget(IPC_PRIVATE, N_MEMORY_SIZE, S_IRUSR | S_IWUSR); // Create a shared memory segment of size N ints for final_arr
  79. if ( finalSId < 0 ) errormsg( "ERROR in creating a shared memory segment for FINAL ARRAY\n" );
  80.  
  81. workingSId = shmget(IPC_PRIVATE, M_MEMORY_SIZE, S_IRUSR | S_IWUSR); // Create a shared memory segment of size M ints for working array
  82. if ( workingSId < 0 ) errormsg( "ERROR in creating a shared memory segment for WORKING ARRAY\n" );
  83.  
  84. // Read num values from the input file specified
  85. FILE* inFile = fopen(input_file, "rb");
  86. int num = 0; // Used to read each number in the file
  87. int numCount; // Stores the count of numbers in the input file to compare with N later
  88. for(numCount = 0; fscanf(inFile, "%d", &num) && !feof(inFile); numCount++)
  89. if (numCount < n){ // Make sure that the number of values in the input file do not exceed n (size of input_arr)
  90. input_arr[numCount] = num; // Store each num value in the input_arr
  91. }
  92. fclose(inFile);
  93.  
  94. // If the count of numbers in the file do not match the one specified in command line parameter N
  95. if (numCount != n){
  96. // Output an error
  97. printf("Input value n does not match the number of elemts in the input file.\n");
  98. return 1;
  99. }
  100.  
  101. // Get the final and temp arrays from shared memory
  102. final_arr = (int *) shmat(finalSId, NULL, 0);
  103. temp_arr = (int *) shmat(tempSId, NULL, 0);
  104. working = (int *) shmat(workingSId, NULL, 0);
  105.  
  106. // Fill the temp array with the initial input numbers
  107. for(int i = 0; i < n; i++){
  108. temp_arr[i] = input_arr[i];
  109. }
  110.  
  111. // Each process will have a personal id
  112. // The id will be used for the process to figure out which index it needs to compute
  113.  
  114. // Create M processes
  115. if (m > 1){
  116. pid = fork(); // Create a child
  117. while(pid < 0){
  118. pid = fork();
  119. }
  120. for( int i=1; i< m-1; i++) { // Iterate m times
  121. if (pid == 0) { // For every child
  122. id = i; // Assign the index/id to the child
  123. pid = fork(); // Create a new child
  124. while(pid < 0){
  125. pid = fork();
  126. }
  127. }
  128. }
  129. if (pid == 0){
  130. id = m - 1; // For the first child, set index to 1
  131. }
  132. }
  133.  
  134. // Iterate log(n, base2) times
  135. for (int iter=0; iter<numIter; iter++) {
  136. // Declare that the id (current child) is ready to work
  137. working[id] = 1;
  138.  
  139. // Wait until each process is ready to start working
  140. do {
  141. // Get the updated/current version from the shared memory
  142. working = (int *) shmat(workingSId, NULL, 0);
  143. // Hey sexy
  144. // Steven Lo and Nikhil Patil wrote this genius program
  145. } while(sum(working, m) != m);
  146.  
  147. //printf("Starting work for iteration (%d) and id :: %d\n", iter, id);
  148.  
  149. // This print is SACRED. NO TOUCH. THIS IS LEGACY MODULE
  150. printf("Working[%d] :: %d\n", id, working[id]);
  151. // Honestly tho, wth. Why does this comment make/break the code
  152. // It was placed here for OPTIMAL debugging purposes
  153.  
  154. // Calculate unique index values in final based on id
  155. // Ex: n = 10, m = 3
  156. // id=0 is responsible for index (0, 3, 6, 9)
  157. // id=1 is responsible for index (1, 4, 7, 10)
  158. // id=2 is responsible for index (2, 5, 8)
  159. for (int j = id; j < n; j += m){ // Calculate final[j], increment j by number of processes for the next index
  160. if (j - pow(2,iter) < 0){
  161. final_arr[j] = temp_arr[j]; // Directly copy the values if new values can't be computed from previous array
  162. }
  163. else{
  164. final_arr[j] = temp_arr[j] + temp_arr[j-(int)(pow(2,iter))]; // Compute values from previous array
  165. }
  166. }
  167.  
  168. // Declare the work finished
  169. working[id] = 0;
  170.  
  171. // Wait until all processes are finished
  172. do {
  173. // Get the updated/current version from the shared memory
  174. working = (int *) shmat(workingSId, NULL, 0);
  175. // Hey sexy
  176. // Steven Lo and Nikhil Patil wrote this genius program
  177. } while(sum(working, m) != 0); // Check if the sum of all elements in working array is equal to 0
  178.  
  179. // Output the final array to the terminal
  180. // Apparently this is also part of LEGACY CODE
  181. for(int i = 0; i < n; i++){
  182. printf("%d ", final_arr[i]);
  183. }
  184. printf("\n");
  185. // DO NOT MODIFY/DELETE this loop either
  186.  
  187. // Copy all values from final to temp
  188. for(int i = 0; i < n && iter != numIter-1; i++){
  189. temp_arr[i] = final_arr[i];
  190. }
  191.  
  192. // Go to next iteration :D
  193. }
  194.  
  195. // Kill all processes to prevent any zombies
  196. for(int i = 0; i < m; i++){
  197. wait(NULL);
  198. }
  199.  
  200. // Create an output file stream
  201. FILE* outFile = fopen(output_file, "w");
  202. if (outFile != NULL){
  203. for(int i = 0; i < n; i++){
  204. fprintf(outFile, "%d ", final_arr[i]); // Print the final array to the file
  205. }
  206. }
  207. fprintf(outFile, "\n"); // Print an empty line at the end of the file
  208. fclose(outFile); // Close the file stream
  209. printf("\n"); // Print an empty line on terminal
  210.  
  211. // Break the link between local and shared memory
  212. shmdt(final_arr);
  213. shmdt(temp_arr);
  214. shmdt(working);
  215.  
  216. // Remove shared memory segment
  217. shmctl(finalSId, IPC_RMID, NULL);
  218. shmctl(tempSId, IPC_RMID, NULL);
  219. shmctl(workingSId, IPC_RMID, NULL);
  220.  
  221. return 0;
  222. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement