-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
151 lines (132 loc) · 5.03 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Iterative C program for merge sort */
/*
*
* This CUDA mergesort program uses code and algorithms from Dr. Steven S.
* Lumetta, Dr. Wen-mei W. Hwu , Dr. David Kirk, Dr. Christian Siebert, and
* Dr. Jesper Larsson Träff, as well as the iterative mergesort algorithm as
* detailed on the https://www.geeksforgeeks.org/iterative-merge-sort/ page :)
* Author: Yensong Ted Li
*
*/
#include "main.h"
#include <errno.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "splitmix64.h"
#include "xoshiro256starstar.h"
// Seed for pseudorandom number generator that creates the array to be sorted
#define RAND_NUM_SEED 1234
// Think twice before changing any macro definition below this comment.
#define NUM_NS_PER_SEC 1000000000.0
#define MAX_USER_INPUT_LEN 21
#define USER_INPUT_NUM_BASE 10
/* Driver program to test parallel mergesort */
int main() {
bool sort_non_descending = true;
long input_array_length = 0;
const char sort_non_descending_req_char = 'T';
char* fgets_return_stat = NULL;
char user_input[MAX_USER_INPUT_LEN + 1] = {'\0'};
char* remaining_non_ulong;
while (fgets_return_stat == NULL) {
// printf("WTF IS THIS: %ld.\n", get_max_arr_len_for_dev(sizeof(double)));
printf(
"Enter the size of the array to be sorted (BY ENTERING A SIZE YOU "
"ALSO\n"
"\tAGREE TO NOT LAUNCH NEW APPS ON THE PRIMARY GPU WHEN THIS PROGRAM\n"
"\tIS RUNNING): ");
fgets_return_stat = fgets(user_input, MAX_USER_INPUT_LEN + 1, stdin);
// Remove any trailing newline and carriage returns
user_input[strcspn(user_input, "\r\n")] = '\0';
if (fgets_return_stat != NULL) {
errno = 0;
input_array_length =
strtoul(user_input, &remaining_non_ulong, USER_INPUT_NUM_BASE);
int strtol_error_status = errno;
if (strtol_error_status != 0 || remaining_non_ulong[0] != '\0' ||
input_array_length < 1 ||
input_array_length > get_max_arr_len_for_dev(sizeof(double))) {
fgets_return_stat = NULL;
printf(
"Error: invalid input - please press enter again to bring back up\n"
"\tarray size prompt if neccessary.\n");
// Clear remainder of input buffer
int next_char = getchar();
while (next_char != ((int)'\n') && next_char != EOF) {
next_char = getchar();
}
}
}
}
printf(
"Enter anything starting with \"T\" (without the quotes) for sorting\n"
"\tnon-descending, anything else (including nothing) for\n"
"\tsorting non-ascending: ");
fgets_return_stat = fgets(user_input, MAX_USER_INPUT_LEN + 1, stdin);
// Remove any trailing newline and carriage returns
user_input[strcspn(user_input, "\r\n")] = '\0';
if (user_input[0] != sort_non_descending_req_char) {
sort_non_descending = false;
}
set_seed_splitmix64(RAND_NUM_SEED);
init_xoshiro256starstar();
double* arr = (double*)malloc(input_array_length * sizeof(*arr));
for (long index = 0; index < input_array_length; index++) {
double temp = u64_to_double_conv(xoshiro256starstar_get_next());
if (isnan(temp)) {
temp = INFINITY;
}
arr[index] = temp;
}
printf("\nStarting sorting on GPU...\n");
struct timespec start_func_call, end_func_call;
timespec_get(&start_func_call, TIME_UTC);
parallel_merge_sort(arr, input_array_length, sort_non_descending);
timespec_get(&end_func_call, TIME_UTC);
printf("Ended sorting on GPU!\n");
bool sort_correctly = true;
long uniq_nums_count = 0;
for (long index = 1; index < input_array_length; ++index) {
if (sort_non_descending && arr[index - 1] > arr[index]) {
printf(
"Sorting failed using parallel_merge_sort!\n"
"Expected %lf at index %ld to be LESS THAN OR \n"
"EQUAL TO %lf at index %ld\n",
arr[index - 1], index - 1, arr[index], index);
sort_correctly = false;
break;
} else if (!sort_non_descending && arr[index - 1] < arr[index]) {
printf(
"Sorting failed using parallel_merge_sort!\n"
"Expected %lf at index %ld to be GREATER THAN OR \n"
"EQUAL TO %lf at index %ld\n",
arr[index - 1], index - 1, arr[index], index);
sort_correctly = false;
break;
}
// Get number of unique numbers for sanity check.
uint64_t first_num_u64 = double_to_u64_conv(arr[index - 1]);
uint64_t second_num_u64 = double_to_u64_conv(arr[index]);
if (second_num_u64 != first_num_u64) {
++uniq_nums_count;
}
}
if (sort_correctly) {
printf("Sorting %s succeeded using parallel_merge_sort!\n",
sort_non_descending ? "non-descending" : "non-ascending");
}
printf(
"Time took to sort array of length %ld on GPU: %lf seconds.\n"
"We ended up with %ld unique numbers.\n",
input_array_length,
difftime(end_func_call.tv_sec, start_func_call.tv_sec) +
(((double)(end_func_call.tv_nsec - start_func_call.tv_nsec)) /
NUM_NS_PER_SEC),
uniq_nums_count);
free(arr);
return EXIT_SUCCESS;
}