Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions automate.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

long long sequential_compute(const char *path,
long long (*f)(long long, long long));

long long parallel_compute(const char *path,
int n_proc,
long long (*f)(long long, long long));

long long add(long long a, long long b){ return a + b; }
long long mul(long long a, long long b){ return a * b; }
long long mx (long long a, long long b){ return a > b ? a : b; }

void generate_numbers(const char *path, int N)
{
FILE *fp = fopen(path,"w");
if(!fp)
{
perror("fopen");
exit(1);
}

for(int i=0;i<N;i++)
{
fprintf(fp,"%d",rand()%100 + 1);
if(i < N-1) fprintf(fp,",");
}

fclose(fp);
}

int main()
{
const char *path = "numbers.txt";

srand(time(NULL));

FILE *out = fopen("results.csv","w");
if(!out)
{
perror("fopen");
return 1;
}

fprintf(out,"N,seq_time,par_time\n");

for(int N = 1000; N <= 5000000; N += 100000)
{
generate_numbers(path,N);

clock_t start,end;

// sequential
start = clock();
sequential_compute(path,add);
sequential_compute(path,mul);
sequential_compute(path,mx);
end = clock();

double seq_time =
(double)(end-start)/CLOCKS_PER_SEC;

// parallel
start = clock();
parallel_compute(path,7,add);
parallel_compute(path,7,mul);
parallel_compute(path,7,mx);
end = clock();

double par_time =
(double)(end-start)/CLOCKS_PER_SEC;

fprintf(out,"%d,%f,%f\n",N,seq_time,par_time);

printf("Test N=%d complete\n",N);
}

fclose(out);

printf("Results saved to results.csv\n");

return 0;
}
54 changes: 54 additions & 0 deletions automate2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <stdio.h>
#include <time.h>

long long sequential_compute(const char *path,
long long (*f)(long long, long long));

long long parallel_compute(const char *path,
int n_proc,
long long (*f)(long long, long long));

long long add(long long a, long long b){ return a + b; }
long long mul(long long a, long long b){ return a * b; }
long long mx (long long a, long long b){ return a > b ? a : b; }

int main()
{
const char *path = "numbers.txt";

FILE *out = fopen("process_scaling.csv","w");
if(!out)
{
perror("fopen");
return 1;
}

fprintf(out,"processes,time\n");

// different numbers of processes
for(int p = 1; p <= 16; p++)
{
clock_t start,end;

start = clock();

parallel_compute(path,p,add);
parallel_compute(path,p,mul);
parallel_compute(path,p,mx);

end = clock();

double time_taken =
(double)(end-start)/CLOCKS_PER_SEC;

fprintf(out,"%d,%f\n",p,time_taken);

printf("Processes %d done\n",p);
}

fclose(out);

printf("Results saved to process_scaling.csv\n");

return 0;
}
163 changes: 163 additions & 0 deletions compute.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>

static long long *read_numbers(const char *path, int *out_n){
FILE *fp = fopen(path, "r");
if (!fp) { perror("fopen"); return NULL;}
int cap = 64, n = 0;
long long *arr = malloc(cap * sizeof *arr);
if (!arr) {fclose(fp); return NULL;}
long long v;
while (fscanf(fp, " %lld", &v) == 1){
if (n == cap){
cap *= 2;
long long *tmp = realloc(arr, cap * sizeof *arr);
if (!tmp) {free(arr); fclose(fp); return NULL;}
arr = tmp;}
arr[n++] = v;
int c = fgetc(fp);
if (c != ',' && c != EOF) ungetc(c, fp);
}

fclose(fp);
*out_n = n;
return arr;
}

static long long reduce(const long long *arr, int n,long long (*f)(long long, long long)){
long long acc = arr[0];
for (int i = 1; i < n; i++) acc = f(acc, arr[i]);
return acc;}

long long sequential_compute(const char *path,long long (*f)(long long, long long)){
int n;
long long *arr = read_numbers(path, &n);
if (!arr || n == 0){
free(arr);
fprintf(stderr, "sequential_compute: no numbers read\n");
return LLONG_MIN;
}
long long acc = arr[n - 1];
for (int i = n - 1; i-- > 0; ) acc = f(arr[i], acc);
free(arr);
return acc;
}

long long parallel_compute(const char *path,int n_proc,long long (*f)(long long, long long)){
if (n_proc <= 0){
fprintf(stderr, "parallel_compute: n_proc must be > 0\n");
return LLONG_MIN;}

int n;
long long *arr = read_numbers(path, &n);
if (!arr || n == 0){
free(arr);
fprintf(stderr, "parallel_compute: no numbers read\n");
return LLONG_MIN;}

if (n_proc > n) n_proc = n;
int chunk = n / n_proc;
int leftover = n % n_proc;
int (*pipes)[2] = malloc(n_proc * sizeof *pipes);
pid_t *pids = malloc(n_proc * sizeof *pids);
if (!pipes || !pids) {
free(arr); free(pipes); free(pids);
return LLONG_MIN;
}

for (int i = 0; i < n_proc; i++){
if (pipe(pipes[i]) == -1){
perror("pipe");
for (int j = 0; j < i; j++){
close(pipes[j][0]);
close(pipes[j][1]);}
free(arr); free(pipes); free(pids);
return LLONG_MIN;
}
}

int spawned = 0;
for (int i = 0; i < n_proc; i++){
int start = i*chunk;
int end = start + chunk + (i == n_proc - 1 ? leftover : 0);

pids[i] = fork();
if (pids[i] < 0){
perror("fork");
for (int j = 0; j < spawned;j++){
kill(pids[j], SIGTERM);
waitpid(pids[j], NULL, 0);}
for (int j = 0; j < n_proc;j++){
close(pipes[j][0]);
close(pipes[j][1]);}
free(arr); free(pipes); free(pids);
return LLONG_MIN;}

if (pids[i] == 0) {
for (int j = 0; j < n_proc; j++) {
close(pipes[j][0]);
if (j != i) close(pipes[j][1]);}
long long partial = reduce(arr + start, end - start, f);
int written = write(pipes[i][1], &partial, sizeof partial);
(void)written;
close(pipes[i][1]);
free(arr); free(pipes); free(pids);
_exit(0);
}
spawned++;}

for (int i = 0; i < n_proc; i++)
close(pipes[i][1]);

long long *partials = malloc(n_proc * sizeof *partials);
if (!partials) {
for (int i = 0; i < n_proc; i++) close(pipes[i][0]);
for (int i = 0; i < n_proc; i++) waitpid(pids[i], NULL, 0);
free(arr); free(pipes); free(pids);
return LLONG_MIN;
}

for (int i = 0; i < n_proc; i++){
int r = read(pipes[i][0], &partials[i], sizeof partials[i]);
if (r != (int)sizeof partials[i]){
fprintf(stderr, "parallel_compute: short read from child %d\n", i);
partials[i] = 0;
}
close(pipes[i][0]);}
for (int i = 0; i < n_proc; i++) waitpid(pids[i], NULL, 0);

long long result = reduce(partials,n_proc,f);

free(arr); free(pipes); free(pids); free(partials);
return result;
}

#ifdef COMPUTE_TEST
long long add(long long a, long long b) { return a + b;}
long long mul(long long a, long long b) { return a * b;}
long long mx (long long a, long long b) { return a > b? a : b;}

int main(int argc, char *argv[])
{
const char *path = argc > 1 ? argv[1] : "numbers.txt";

printf("Part1-sequential_compute\n");
printf("sum = %lld\n", sequential_compute(path, add));
printf("product = %lld\n", sequential_compute(path, mul));
printf("max = %lld\n", sequential_compute(path, mx));

printf("\nPart2-parallel_compute (4 procs)\n");
printf("sum = %lld\n", parallel_compute(path, 4, add));
printf("prod = %lld\n", parallel_compute(path, 4, mul));
printf("max = %lld\n", parallel_compute(path, 4, mx));

return 0;
}
#endif


1 change: 1 addition & 0 deletions numbers.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1,2,3,4,5,6,7,8,9,10
17 changes: 17 additions & 0 deletions process_scaling.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
processes,time
1,2.502263
2,2.398349
3,2.442807
4,2.675024
5,2.558864
6,2.229776
7,2.031597
8,2.047933
9,2.423471
10,2.503948
11,2.393296
12,2.291219
13,2.233890
14,2.167401
15,2.411243
16,2.153978
51 changes: 51 additions & 0 deletions results.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
N,seq_time,par_time
1000,0.000278,0.001678
101000,0.025293,0.028198
201000,0.055328,0.058385
301000,0.092299,0.098093
401000,0.133344,0.132219
501000,0.171204,0.163994
601000,0.209125,0.197229
701000,0.242274,0.251044
801000,0.285125,0.271136
901000,0.332160,0.305844
1001000,0.347259,0.394467
1101000,0.480947,0.440557
1201000,0.527320,0.437721
1301000,0.446075,0.469071
1401000,0.515478,0.436285
1501000,0.524197,0.468181
1601000,0.521664,0.490741
1701000,0.549413,0.550071
1801000,0.731894,0.778137
1901000,0.821788,0.815614
2001000,0.710408,0.728659
2101000,0.862667,0.963047
2201000,1.045063,1.033249
2301000,0.935393,1.195454
2401000,1.548874,1.030068
2501000,1.111333,0.906074
2601000,1.219223,1.447804
2701000,1.374043,1.302392
2801000,1.734898,1.318979
2901000,1.080929,1.128941
3001000,1.304952,1.258263
3101000,1.017442,1.010833
3201000,1.290110,1.170737
3301000,1.316924,1.042860
3401000,1.418169,1.212233
3501000,1.538255,1.287164
3601000,1.268677,1.459031
3701000,1.401894,1.390480
3801000,1.425571,1.417154
3901000,1.659142,1.307537
4001000,1.685081,1.344943
4101000,1.305627,1.188571
4201000,1.384767,1.294613
4301000,1.448628,1.337252
4401000,1.468510,1.604637
4501000,1.641293,1.589458
4601000,1.671218,1.602195
4701000,1.619908,1.699248
4801000,1.650899,1.657043
4901000,1.700224,1.624811