-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPrefixSumSharedAlgorithm2.c
More file actions
161 lines (144 loc) · 5.68 KB
/
Copy pathPrefixSumSharedAlgorithm2.c
File metadata and controls
161 lines (144 loc) · 5.68 KB
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
152
153
154
155
156
157
158
/*
* This program calculates the prefix sum or prefix multiplication of an array of random numbers.
* This approach is serial and uses a single thread.
* The program takes the following command line arguments:
* -s <size> : size of the array (default: 4194304)
* -r <seed> : seed for the random number generator (default: current time)
* -f <function> : function to execute (prefixSum or prefixMult, default: prefixSum)
* -o <outputFile> : output file to write the results (default: /dev/null)
* -i <inputFile> : input file to read the array from (default: /dev/null)
* -t <threads> : number of threads to use (default: 8)
* Example: ./PrefixSumSerial -s 100 -r 1 -f prefixSum -o output.txt -i input.txt
* Instructor: Dr. Jeffery Bush
* compile with: gcc-13 -Wall -O3 -fopenmp -march=native PrefixSumSharedAlgorithm2.c -o PrefixSumSharedAlgorithm2 -lm
* Exameple: ./PrefixSumShared -s 100 -r 1 -f prefixSum -o output.txt -i input.txt -t 8
* Authors: Yousuf Kanan and Derek Allmon
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <omp.h>
void prefixSumShared(double *arr, int size, int numThreads) {
int max_depth = (int)ceil(log2(size)); // Calculate once and cast to integer
#pragma omp parallel for num_threads(numThreads)
for (int d = 0; d < max_depth; d++) {
int step = 1 << (d + 1);
for (int i = step - 1; i < size; i += step) {
arr[i] += arr[i - (step >> 1)];
}
}
// Reverse phase of the Blelloch scan
arr[size - 1] = 0; // Set last element to zero before reverse phase
for (int d = max_depth - 1; d >= 0; d--) {
int step = 1 << (d + 1);
#pragma omp parallel for num_threads(numThreads)
for (int i = step - 1; i < size; i += step) {
double temp = arr[i - (step >> 1)];
arr[i - (step >> 1)] = arr[i];
arr[i] += temp;
}
}
}
void prefixMultShared(double *arr, int size, int numThreads) {
int max_depth = (int)ceil(log2(size)); // Calculate once and cast to integer
#pragma omp parallel for num_threads(numThreads)
for (int d = 0; d < max_depth; d++) {
int step = 1 << (d + 1);
for (int i = step - 1; i < size; i += step) {
arr[i] *= arr[i - (step >> 1)];
}
}
// Reverse phase of the Blelloch scan
arr[size - 1] = 1; // Set last element to one before reverse phase
for (int d = max_depth - 1; d >= 0; d--) {
int step = 1 << (d + 1);
#pragma omp parallel for num_threads(numThreads)
for (int i = step - 1; i < size; i += step) {
double temp = arr[i - (step >> 1)];
arr[i - (step >> 1)] = arr[i];
arr[i] *= temp;
}
}
}
// -s <size> : size of the array (default: 4194304) -r <seed> : seed for the random number generator (default: current time) -f <function> : function to execute (prefixSum or prefixMult, default: prefixSum) -o <outputFile> : output file to write the results (default: /dev/null) -i <inputFile> : input file to read the array from (default: /dev/null) -t <threads> : number of threads to use (default: 8)
void parseArguments(int argc, char **argv, long long *size, unsigned int *seed, void (**function)(double *, int, int), char **outputFile, char **inputFile, int *threads)
{
for (int i = 1; i < argc; i++){
if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) {
*size = atoll(argv[++i]);
}
if (strcmp(argv[i], "-r") == 0 && i + 1 < argc){
*seed = (unsigned int)atoi(argv[++i]);
}
if (strcmp(argv[i], "-f") == 0 && i + 1 < argc) {
if (strcmp(argv[i + 1], "prefixMult") == 0) {
*function = prefixMultShared;
}
else if (strcmp(argv[i + 1], "prefixSum") == 0) {
*function = prefixSumShared;
}
i++;
}
if (strcmp(argv[i], "-o") == 0 && i + 1 < argc) {
*outputFile = argv[++i];
}
if (strcmp(argv[i], "-i") == 0 && i + 1 < argc) {
*inputFile = argv[++i];
}
if (strcmp(argv[i], "-t") == 0 && i + 1 < argc){
*threads = atoi(argv[++i]);
}
}
}
double *initializeArray(int size, unsigned int seed) {
double *arr = (double *)malloc(size * sizeof(double));
if (!arr) {
fprintf(stderr, "Memory allocation failed\n");
exit(1);
}
unsigned int rand_state = seed;
srand(seed);
for (int i = 0; i < size; i++) {
arr[i] = (double)rand_r(&rand_state) / (double)RAND_MAX * 2;
}
return arr;
}
void writeOutputFile(double *arr, long long size, char *outputFile)
{
if (strcmp(outputFile, "/dev/null") == 0)
{
return;
}
FILE *file = fopen(outputFile, "w");
if (!file)
{
fprintf(stderr, "Failed to open output file\n");
exit(1);
}
for (int i = 0; i < size; i++)
{
fprintf(file, "%lf\n", arr[i]);
}
fclose(file);
}
int main(int argc, char **argv)
{
long long size = 4194304;
unsigned int seed = (unsigned int)time(NULL);
void (*function)(double *, int, int) = prefixSumShared;
char *outputFile = "/dev/null";
char *inputFile = "/dev/null";
int threads = 8;
parseArguments(argc, argv, &size, &seed, &function, &outputFile, &inputFile, &threads);
omp_set_num_threads(threads);
double *arr = initializeArray(size, seed);
double start = omp_get_wtime();
function(arr, size, threads);
double end = omp_get_wtime();
printf("%llu, %f ms\n", size, (end - start) * 1000.0);
writeOutputFile(arr, size, outputFile);
free(arr);
return 0;
}