I want to compare the procedure time for each number of process. I made 5000000 numbers in input.txt
in random order. I read it and do bucket sorting with multiprocessing (let the number of buckets = number of process) and I record the time spending to do bucket sorting. I am wondering if my code is doing multiprocessing well and is it right to take about 1.xx seconds to do it per each number of process? I understand that the hardware performance is the important thing but I think it may be too short.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <time.h>
int N = 5000000; // 숫자의 개수
int numProcessesOptions[] = {1, 3, 5, 7, 10, 20, 40, 70, 100, 150, 200, 250, 300};
int numProcessesCount = sizeof(numProcessesOptions) / sizeof(numProcessesOptions[0]);
// 비교 함수를 정의합니다.
int compareDoubles(const void *a, const void *b) {
return (*(double *)a - *(double *)b > 0) - (*(double *)a - *(double *)b < 0);
}
void bucketSort(double *arr, int n, int processID, int numProcesses) {
// 데이터를 분할합니다.
int chunkSize = N / numProcesses;
int startIndex = processID * chunkSize;
int endIndex = (processID == numProcesses - 1) ? N : (processID + 1) * chunkSize;
// 버킷 소트를 수행합니다.
int *buckets = (int *)calloc(chunkSize, sizeof(int));
if (buckets == NULL) {
perror("메모리 할당 실패");
exit(1);
}
for (int i = startIndex; i < endIndex; i++) {
int index = (int)((arr[i] - 1.0) * chunkSize);
buckets[index]++;
}
int index = startIndex;
for (int i = 0; i < chunkSize; i++) {
while (buckets[i] > 0) {
arr[index++] = (double)i / chunkSize + 1.0;
buckets[i]--;
}
}
free(buckets);
}
void writeToFile(double *arr, int n, char *filename) {
FILE *outputFile = fopen(filename, "w");
if (outputFile == NULL) {
perror("파일을 열 수 없습니다.");
return;
}
for (int i = 0; i < n; i++) {
fprintf(outputFile, "%lf\n", arr[i]); // 소수점 10자리까지 출력
}
fclose(outputFile);
}
void mergeData(double *arr, int n, int numProcesses) {
double *mergedData = (double *)malloc(N * sizeof(double));
if (mergedData == NULL) {
perror("메모리 할당 실패");
exit(1);
}
int chunkSize = N / numProcesses;
int process = 0;
for (int i = 0; i < N; i++) {
if (i % chunkSize == 0 && process < numProcesses) {
process++;
}
mergedData[i] = arr[i];
}
// 모든 프로세스에서 생성된 데이터를 병합하여 정렬합니다.
qsort(mergedData, N, sizeof(double), compareDoubles);
// 정렬된 데이터를 파일에 저장합니다.
writeToFile(mergedData, N, "output.txt");
free(mergedData);
}
void sortAndMeasureTime(int numProcesses) {
double *numbers = (double *)malloc(N * sizeof(double));
if (numbers == NULL) {
perror("메모리 할당 실패");
return;
}
for (int i = 0; i < N; i++) {
// 데이터 초기화 (1.0부터 5000000까지)
numbers[i] = i + 1.0;
}
clock_t start_time = clock();
// 각 프로세스에서 데이터를 버킷 소트합니다.
for (int i = 0; i < numProcesses; i++) {
pid_t pid = fork();
if (pid == 0) {
// 자식 프로세스에서 버킷 소트 수행
bucketSort(numbers, N, i, numProcesses);
exit(0);
} else if (pid < 0) {
perror("프로세스 생성 실패");
exit(1);
}
}
// 모든 자식 프로세스의 종료를 기다립니다.
for (int i = 0; i < numProcesses; i++) {
int status;
wait(&status);
}
// 모든 프로세스에서 생성된 데이터를 병합하여 정렬합니다.
mergeData(numbers, N, numProcesses);
clock_t end_time = clock();
double total_time = (double)(end_time - start_time) / CLOCKS_PER_SEC;
free(numbers); // 메모리 해제
printf("Process: %d, Time: %.5f seconds\n", numProcesses, total_time);
}
int main() {
for (int i = 0; i < numProcessesCount; i++) {
sortAndMeasureTime(numProcessesOptions[i]);
}
return 0;
}