]> vgcfreebox.myrthtech.pt Git - ue-pp-sortingalgorith.git/blob - parallel-sorting.c
python random number generator and c sorting algorith
[ue-pp-sortingalgorith.git] / parallel-sorting.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <omp.h>
5
6 // Global variables (simulating shared memory access for simplicity)
7 int* data = NULL;
8 size_t data_size = 0;
9
10 /**
11 * @brief Merges two sorted sub-arrays (data[low...mid] and data[mid+1...high]).
12 * NOTE: This function must manually manage temporary memory allocation and deallocation.
13 */
14 void merge(int low, int mid, int high) {
15 // Calculate sizes of the two halves
16 int n1 = mid - low + 1;
17 int n2 = high - mid;
18
19 // --- Manual Memory Allocation for Temporary Arrays ---
20 // We must allocate space for L and R.
21 int* L = (int*)malloc(n1 * sizeof(int));
22 int* R = (int*)malloc(n2 * sizeof(int));
23
24 if (L == NULL || R == NULL) {
25 perror("Failed to allocate temporary merge arrays");
26 exit(EXIT_FAILURE);
27 }
28
29 // Copy data from the main array into the temporary arrays
30 for (int i = 0; i < n1; i++) {
31 L[i] = data[low + i];
32 }
33 for (int j = 0; j < n2; j++) {
34 R[j] = data[mid + 1 + j];
35 }
36
37 // Standard sequential merging logic
38 int i = 0; // Index for L
39 int j = 0; // Index for R
40 int k = low; // Index for the main data array
41
42 while (i < n1 && j < n2) {
43 if (L[i] <= R[j]) {
44 data[k++] = L[i++];
45 } else {
46 data[k++] = R[j++];
47 }
48 }
49
50 // Copy remaining elements of L
51 while (i < n1) {
52 data[k++] = L[i++];
53 }
54
55 // Copy remaining elements of R
56 while (j < n2) {
57 data[k++] = R[j++];
58 }
59
60 // --- Crucial Step: Manual Memory Cleanup ---
61 free(L);
62 free(R);
63 }
64
65 /**
66 * @brief Recursive function to perform parallel Merge Sort using OpenMP.
67 */
68 void parallel_merge_sort(int low, int high) {
69 if (low < high) {
70 int mid = low + (high - low) / 2;
71
72 // Use OpenMP sections to parallelize the recursive calls
73 // The OpenMP runtime handles the threads assignment and synchronization.
74 #pragma omp parallel sections
75 {
76 #pragma omp section
77 {
78 // Recurse on the left half
79 parallel_merge_sort(low, mid);
80 }
81 #pragma omp section
82 {
83 // Recurse on the right half
84 parallel_merge_sort(mid + 1, high);
85 }
86 }
87 // Implicit barrier ensures merge only happens when both halves are sorted.
88 // Combine the two sorted halves
89 merge(low, mid, high);
90 }
91 }
92
93
94 /**
95 * @brief Reads all integers from the specified input file.
96 * @return 1 on success, 0 on failure.
97 */
98 int read_file(const char* filename) {
99 FILE* infile = fopen(filename, "r");
100 if (infile == NULL) {
101 perror("Error opening input file");
102 return 0;
103 }
104
105 // Initial allocation (guessing a reasonable maximum size)
106 size_t capacity = 1024;
107 data = (int*)malloc(capacity * sizeof(int));
108 if (data == NULL) {
109 perror("Memory allocation failed for data array");
110 fclose(infile);
111 return 0;
112 }
113 int count = 0;
114
115 int num;
116 while (fscanf(infile, "%d", &num) == 1) {
117 // Check if realloc is necessary
118 if (count == capacity - 1) {
119 capacity *= 2;
120 int* new_data = (int*)realloc(data, capacity * sizeof(int));
121 if (new_data == NULL) {
122 perror("Failed to reallocate memory for data array");
123 free(data);
124 fclose(infile);
125 return 0;
126 }
127 data = new_data;
128 }
129 data[count++] = num;
130 }
131
132 fclose(infile);
133 data_size = count;
134 return 1;
135 }
136
137 /**
138 * @brief Writes the sorted elements to the specified output file.
139 * @return 1 on success, 0 on failure.
140 */
141 int write_file(const char* filename) {
142 FILE* outfile = fopen(filename, "w");
143 if (outfile == NULL) {
144 perror("Error opening output file");
145 return 0;
146 }
147
148 // Write the data sequentially
149 for (size_t i = 0; i < data_size; ++i) {
150 fprintf(outfile, "%d\n", data[i]);
151 }
152
153 fclose(outfile);
154 return 1;
155 }
156
157
158 int main(int argc, char *argv[]) {
159 // --- 1. Handle Command Line Arguments ---
160 int thread_count = -1;
161 char *input_file = NULL;
162 char *output_file = NULL;
163
164 for (int i = 1; i < argc; ++i) {
165 if (strcmp(argv[i], "-t") == 0 && i + 1 < argc) {
166 // Get thread count from the next argument
167 thread_count = atoi(argv[i+1]);
168 i++; // Skip the argument after -t
169 } else if (input_file == NULL) {
170 input_file = argv[i];
171 } else if (output_file == NULL) {
172 output_file = argv[i];
173 }
174 }
175
176 // Check for mandatory arguments and thread count
177 if (thread_count <= 0 || input_file == NULL || output_file == NULL) {
178 fprintf(stderr, "Usage: %s <input_file> <output_file> [-t <thread_count>]\n", argv[0]);
179 return EXIT_FAILURE;
180 }
181
182 // --- 2. Setup OpenMP Threads ---
183 omp_set_num_threads(thread_count);
184 printf("--- Starting Sort Process ---\n");
185 printf("Threads allocated by OpenMP: %d\n", omp_get_max_threads());
186
187 // --- 3. Read Data ---
188 if (!read_file(input_file)) {
189 fprintf(stderr, "Failed to read data.\n");
190 // Clean up data memory before exit
191 free(data);
192 return EXIT_FAILURE;
193 }
194 printf("Successfully read %zu elements from %s\n", data_size, input_file);
195
196 // --- 4. Sort Data ---
197 if (data_size > 0) {
198 // Execute the parallel sort
199 parallel_merge_sort(0, data_size - 1);
200 printf("Sorting completed successfully.\n");
201 }
202
203 // --- 5. Write Results ---
204 if (!write_file(output_file)) {
205 fprintf(stderr, "Failed to write output data.\n");
206 free(data);
207 return EXIT_FAILURE;
208 }
209 printf("Sorted data written successfully to %s\n", output_file);
210
211 // --- 6. Cleanup ---
212 free(data);
213 return EXIT_SUCCESS;
214 }