Commit 052d520f authored by kjc015's avatar kjc015
Browse files

Lab 12, Complete

parent d13a1132
CFLAGS = -g -Wall -Werror -fopenmp
CC = gcc
exec = omp_hello omp_add selection_sort omp_selection_sort
all: $(exec)
clean:
rm -f $(exec) *.o
Kyle Chrysler
Section 63
Selection Sort:
2^14
real 0m0.278s
user 0m0.276s
sys 0m0.002s
2^16
real 0m4.477s
user 0m4.474s
sys 0m0.001s
2^18
real 1m11.661s
user 1m11.642s
sys 0m0.008s
Omp Selection Sort 16 Threads:
2^14
real 0m0.010s
user 0m0.067s
sys 0m0.004s
2^16
real 0m0.035s
user 0m0.342s
sys 0m0.002s
2^18
real 0m0.456s
user 0m4.612s
sys 0m0.004s
Omp Selection Sort 64 Threads:
2^14
real 0m0.009s
user 0m0.010s
sys 0m0.004s
2^16
real 0m0.018s
user 0m0.078s
sys 0m0.008s
real 0m0.128s
user 0m1.245s
sys 0m0.010s
2^18
/*
* https://www.openmp.org/wp-content/uploads/omp-hands-on-SC08.pdf
* 2020-04-05
* Downloaded for CSCI 206, spring 2020
* with minor format revision
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <omp.h>
// array sum of n elements, nothing special here
double sum_array(double * a, int n)
{
double sum = 0;
while(n--){
sum += *a++;
}
return sum;
}
// pseudo random array filler
void fill_array(int seed, double * a, int n)
{
if (n == 16){
// constant data if n == 16
double d[16] = {4,4,4,4,7,7,7,7,1,1,1,1,5,5,5,5};
memcpy(a, d, sizeof(double)*16);
return;
}
srand(seed);
while(n--){
// rand returns an int between 0 and RAND_MAX, this maps it to [0...1]
*a++ = (double)rand() / (double)RAND_MAX;
}
}
// print an array of size n
void print_array(double * a, int n)
{
int i;
printf("[");
for (i=0; i<n-1; i++){
printf("%f, ", *a++);
if (i > 15){
//truncate array here
printf("...]\n");
return;
}
}
printf("%f]\n", *a++);
}
int main(int argc, char * argv[])
{
int i; // loop counter, etc
int NUM_THREADS; // how many threads to use
int NUM_VALS; // how many values to sum
double * a = NULL; // the array of values
double * par_sums = NULL; // array to store partial results
double sum; // the final sum
double checkval; // sequntial sum result (for verification)
switch (argc){
case 1: // no arguments, use default values
NUM_VALS = 16;
NUM_THREADS = 4;
break;
case 2: // just one argument, NUM_VALS
NUM_VALS = atof(argv[1]);
NUM_THREADS = 4;
break;
default: // command line sets both values
NUM_VALS = atof(argv[1]);
NUM_THREADS = atof(argv[2]);
}
printf("omp_add using %d threads on array of %d elements.\n",
NUM_THREADS,
NUM_VALS);
if (NUM_VALS % NUM_THREADS != 0){
printf("ERROR: array size must be evenly divisible by the number of threads!\n");
exit(254);
}
omp_set_num_threads(NUM_THREADS); // request NUM_THREADS threads
a = malloc(sizeof(double)*NUM_VALS); // allocate memory for array
par_sums = malloc(sizeof(double)*NUM_THREADS); // allocate partial sums
fill_array(1234, a, NUM_VALS); // initialize with random values
printf("Input array: "); // debug output
print_array(a, NUM_VALS);
#pragma omp parallel // execute partial adds in parallel
{
int ID = omp_get_thread_num();
// each block processes NUM_VALS / NUM_THREADS values
int blocksize = NUM_VALS / NUM_THREADS;
// create partial sums
// TODO call the sum_array on the block for this thread ID.
// REPLACE the next line with a call to sum_array!
par_sums[ID] = sum_array(&a[ID*blocksize], blocksize);
}
printf("partial_sums: "); // debug output!
print_array(par_sums, NUM_THREADS);
// now reduce the partial sums to a single sum
sum = 0;
#pragma omp parallel for reduction(+: sum)
for(i=0; i<NUM_THREADS; i++){
sum += par_sums[i];
}
printf("sum = %f\n", sum); // print the final sum
// check the parallel sum by doing it in one shot
checkval = sum_array(a, NUM_VALS);
// becuase of the partial sums, there can be round off differences
// betwen the results!
if (fabs(sum - checkval) > NUM_VALS*1e-6){
printf("ERROR sum is not correct\n");
printf("The correct sum is %f\n", checkval);
exit(255);
}else{
printf("Verified the sum.\n");
}
free(a);
return 0;
}
/*
* https://www.openmp.org/wp-content/uploads/omp-hands-on-SC08.pdf
* 2020-04-05
* Downloaded for CSCI 206, spring 2020
* with minor format revision
*/
#include <stdio.h>
#include <omp.h>
int main(int argc, char * argv[])
{
#pragma omp parallel
{
int ID = omp_get_thread_num();
printf(" hello(%d) ", ID);
printf(" world(%d) \n", ID);
}
printf("We are all done with parallel!\n");
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include <omp.h>
/*
* Students need to fill in the TODO places
*/
/*
* The "merge()" function is adapted from
* https://www.geeksforgeeks.org/merge-sort/
*
* Merges two subarrays of arr[].
* First subarray is arr[l..m]
* Second subarray is arr[m+1..r]
*/
void merge(double arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1; // number on left
int n2 = r - m; // number on right
// debug output
printf("Merge %d %d %d (%d, %d)\n", l, m, r, n1, n2);
/* create temp arrays */
double *L = malloc(sizeof(double) * n1);
double *R = malloc(sizeof(double) * n2);
/* Copy data to temp arrays L[] and R[] */
memcpy(L, arr + l, n1 * sizeof(double));
memcpy(R, arr + m + 1, n2 * sizeof(double));
/* Merge the temp arrays back into arr[l..r]*/
i = 0; // Initial index of first subarray
j = 0; // Initial index of second subarray
k = l; // Initial index of merged subarray
while ((i < n1) && (j < n2))
{
if (L[i] <= R[j])
arr[k++] = L[i++];
else
arr[k++] = R[j++];
}
/* Copy the remaining elements of L[], if there are any */
while (i < n1) arr[k++] = L[i++];
/* Copy the remaining elements of R[], if there are any */
while (j < n2) arr[k++] = R[j++];
free(L);
free(R);
}
// swap two locations (i,j) in the array
void swap(double arr[], int i, int j) {
double tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
void selection_sort(double arr[], int size) {
int i;
int j;
int min_idx;
for (i = 0; i < size-1; i++) {
min_idx = i;
for (j = i+1; j < size; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
swap(arr, min_idx, i);
}
}
/* UTILITY FUNCTIONS */
// print an array of size n
void print_array(double * a, int n){
int i;
if(n <= 16){
// print the whole thing
printf("[");
for (i=0; i<n-1; i++){
printf("%f, ", a[i]);
}
printf("%f]\n", a[i]);
} else {
// truncate the printout
printf("[");
// print first 8
for (i=0; i<8; i++){
printf("%f, ", a[i]);
}
printf("..., ");
// print last 8
for (i=n-9; i < n-1; i++){
printf("%f, ", a[i]);
}
printf("%f]\n", a[i]);
}
}
// pseudo random array filler
void fill_array(int seed, double * a, int n){
if (n == 16){
// constant data if n == 16
const double d[16] = {4,4,4,4,7,7,7,7,1,1,1,1,5,5,5,5};
memcpy(a, d, sizeof(double)*16);
return;
}
srand(seed);
while(n--){
// rand returns an int between 0 and RAND_MAX, this maps it to [0...1]
*a++ = (double)rand() / (double)RAND_MAX;
}
}
// check if an array is sorted, return 1 if true, 0 if not.
int is_sorted(double arr[], int n){
int i;
// check for any out of order elements
for (i=0; i<n-1; i++){
if (arr[i] > arr[i+1])
return 0;
}
return 1;
}
/* Driver program to test above functions */
int main(int argc, char *argv[]) {
int NUM_THREADS; // how many threads to use
int NUM_VALS; // how many values to sum
int blocksize;
double * a = NULL; // the array of values
switch (argc){
case 1: // no arguments, use default values
NUM_VALS = 16;
NUM_THREADS = 4;
break;
case 2: // just one argument, NUM_VALS
NUM_VALS = atof(argv[1]);
NUM_THREADS = 4;
break;
default: // command line sets both values
NUM_VALS = atof(argv[1]);
NUM_THREADS = atof(argv[2]);
}
printf("%s using %d threads on array of %d elements.\n",
argv[0],
NUM_THREADS,
NUM_VALS);
if (NUM_VALS % NUM_THREADS != 0){
printf("ERROR: array size must be evenly divisible by the number of threads!\n");
exit(254);
}
blocksize = NUM_VALS / NUM_THREADS;
omp_set_num_threads(NUM_THREADS); // request NUM_THREADS threads
a = malloc(sizeof(double)*NUM_VALS); // allocate memory for array
fill_array(7891, a, NUM_VALS); // initialize with random values
printf("Generated array ");
print_array(a, NUM_VALS);
printf("Parallel sort\n");
#pragma omp parallel // execute partial sorts in parallel
{
int ID = omp_get_thread_num();
// TODO sort the ID'th block in the array
selection_sort(&a[ID*blocksize], blocksize);
printf("Sorting %d'th %d elenent block.\n", ID, blocksize);
}
printf("Partially sorted array ");
print_array(a, NUM_VALS);
printf("Merge\n");
// TODO Final merge operation on the sorted blocks.
int i;
int j = 1;
while(NUM_THREADS>0){
for(i = 0; i < NUM_THREADS; i++){
int left = i*j*blocksize;
int right = i*j*blocksize + j*blocksize - 1;
int middle = (left+right)/2;
merge(a, left, middle, right);
}
j*=2;
NUM_THREADS = NUM_THREADS/2;
}
printf("Sorted array is ");
print_array(a, NUM_VALS);
printf("Is sorted: %s\n",
is_sorted(a, NUM_VALS) ? "YES": "NO -- FAILED");
free(a);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
/*
* Students need to fill in the TODO places
*/
// swap two locations (i,j) in the array
void swap(double arr[], int i, int j) {
double tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
void selection_sort(double arr[], int size) {
// TODO write selection sort.
int i;
int j;
int min_idx;
for (i = 0; i < size-1; i++) {
min_idx = i;
for (j = i+1; j < size; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
swap(arr, min_idx, i);
}
}
/* UTILITY FUNCTIONS */
// print an array of size n
void print_array(double * a, int n){
int i;
if(n <= 16){
// print the whole thing
printf("[");
for (i=0; i<n-1; i++){
printf("%f, ", a[i]);
}
printf("%f]\n", a[i]);
} else {
// truncate the printout
printf("[");
// print first 8
for (i=0; i<8; i++){
printf("%f, ", a[i]);
}
printf("..., ");
// print last 8
for (i=n-9; i < n-1; i++){
printf("%f, ", a[i]);
}
printf("%f]\n", a[i]);
}
}
// pseudo random array filler
void fill_array(int seed, double * a, int n){
if (n == 16){
// constant data if n == 16
const double d[16] = {4,4,4,4,7,7,7,7,1,1,1,1,5,5,5,5};
memcpy(a, d, sizeof(double)*16);
return;
}
srand(seed);
while(n--){
// rand returns an int between 0 and RAND_MAX, this maps it to [0...1]
*a++ = (double)rand() / (double)RAND_MAX;
}
}
// check if an array is sorted, return 1 if true, 0 if not.
int is_sorted(double arr[], int n){
int i;
// check for any out of order elements
for (i=0; i<n-1; i++){
if (arr[i] > arr[i+1])
return 0;
}
return 1;
}
/* Driver program to test above functions */
int main(int argc, char *argv[]) {
int NUM_THREADS; // how many threads to use
int NUM_VALS; // how many values to sum
double * a = NULL; // the array of values
switch (argc){
case 1: // no arguments, use default values
NUM_VALS = 16;
NUM_THREADS = 1;
break;
case 2: // just one argument, NUM_VALS
NUM_VALS = atof(argv[1]);
NUM_THREADS = 1;
break;
default: // command line sets both values
NUM_VALS = atof(argv[1]);
NUM_THREADS = 1;
}
printf("%s using %d threads on array of %d elements.\n",
argv[0],
NUM_THREADS,
NUM_VALS);
if (NUM_VALS % NUM_THREADS != 0){
printf("ERROR: array size must be evenly divisible by the number of threads!\n");
exit(254);
}
a = malloc(sizeof(double)*NUM_VALS); // allocate memory for array
fill_array(7891, a, NUM_VALS); // initialize with random values
printf("Generated array ");
print_array(a, NUM_VALS);
printf("Sorting. . .\n");
selection_sort(a, NUM_VALS);
printf("Sorted array is ");
print_array(a, NUM_VALS);
printf("Is sorted: %s\n",
is_sorted(a, NUM_VALS) ? "YES": "NO -- FAILED");
free(a);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <time.h>
/*
* Students need to fill in the TODO places
*/
// swap two locations (i,j) in the array
void swap(double arr[], int i, int j) {
double tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
void selection_sort(double arr[], int size) {
// TODO write selection sort.
int i;
int j;
int min_idx;
for (i = 0; i < size-1; i++) {
min_idx = i;
for (j = i+1; j < size; j++)
if (arr[j] < arr[min_idx])
min_idx = j;
// Swap the found minimum element with the first element
swap(arr, min_idx, i);
}
}
/* UTILITY FUNCTIONS */
// print an array of size n
void print_array(double * a, int n){
int i;
if(n <= 16){
// print the whole thing
printf("[");
for (i=0; i<n-1; i++){
printf("%f, ", a[i]);
}
printf("%f]\n", a[i]);
} else {
// truncate the printout
printf("[");
// print first 8
for (i=0; i<8; i++){
printf("%f, ", a[i]);
}
printf("..., ");
// print last 8
for (i=n-9; i < n-1; i++){
printf("%f, ", a[i]);
}
printf("%f]\n", a[i]);
}
}
// pseudo random array filler