Skip to content

Instantly share code, notes, and snippets.

@zed
Last active December 28, 2015 03:49
Show Gist options
  • Select an option

  • Save zed/7437668 to your computer and use it in GitHub Desktop.

Select an option

Save zed/7437668 to your computer and use it in GitHub Desktop.
/* Find sum of an array using forked child processes.
$ gcc -std=gnu99 -Wall -Werror -pedantic parallel-sum-fork.c -lrt && /usr/bin/time ./a.out
http://stackoverflow.com/questions/19934294/how-to-calculate-the-sum-of-the-elements-of-an-array-of-integers-using-p-process
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define PROCNAME "parallel-sum-fork"
typedef intmax_t sum_t;
#define PRI_sum_t PRIiMAX
double perf_counter() {
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tp) < 0) {
perror("clock_gettime");
abort();
}
return tp.tv_sec + tp.tv_nsec * 1e-9;
}
sum_t getsum(sum_t *restrict a, size_t n) {
sum_t sum = 0;
for (size_t i = 0; i < n; ++i)
sum += a[i];
return sum;
}
int main() {
sum_t a[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
};
double start = perf_counter();
int fd[2];
if (pipe(fd) < 0) {
perror("pipe");
exit(EXIT_FAILURE);
}
const int nchildren = 8;
pid_t pid[nchildren];
for (size_t child = 0; child < nchildren; ++child) {
if ((pid[child] = fork()) < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
else if (pid[child] == 0) { // child
intmax_t sum = 0;
close(fd[0]); // close the unused read end of the pipe
for (size_t n = 0; n < 1000000; n+=nchildren)
sum += getsum(a, sizeof(a) / sizeof(*a));
// until sum is written to the parent
for (ssize_t nwritten = 0; nwritten != sizeof(sum); ) {
ssize_t m = write(fd[1], &sum + nwritten, sizeof(sum) - nwritten);
if (m != -1)
nwritten += m;
else if (errno != EINTR) { // error
perror("write");
_exit(EXIT_FAILURE);
}
}
close(fd[1]); // no more results for the parent
_exit(EXIT_SUCCESS); // the child is done
}
}
close(fd[1]); // close the unused write end of the pipe
// parent
int exit_status = EXIT_SUCCESS;
{ // read partial sums
FILE *fp = fdopen(fd[0], "rb");
sum_t psums[nchildren];
if (fp && fread(psums, sizeof(*psums), nchildren, fp) == nchildren) {
printf("got sum: %" PRIiMAX " in %.2f seconds\n",
getsum(psums, nchildren), perf_counter() - start);
}
else {
fputs(PROCNAME ": failed to read partial sums from children\n",
stderr);
exit_status = EXIT_FAILURE;
}
if (fp)
fclose(fp);
// get children statuses
for (size_t child = 0; child < nchildren; ) {
int status = 0;
if (waitpid(pid[child], &status, 0) == -1) {
if (errno != EINTR) {
perror("waitpid");
exit_status = EXIT_FAILURE;
}
else // try again with the same child
continue;
}
else if (WIFEXITED(status)) {
int returncode = WEXITSTATUS(status);
if (returncode != 0)
fprintf(stderr, PROCNAME ": %d child returned non-zero status %d\n",
pid[child], returncode);
}
else if (WIFSIGNALED(status)) {
fprintf(stderr, PROCNAME ": %d child killed by signal %d\n",
pid[child], WTERMSIG(status));
}
else {
fprintf(stderr, PROCNAME ": %d child returned unexpected status %d\n",
pid[child], status);
}
++child; // next child
}
}
exit(exit_status);
}
/* Find sum of an array using openmp.
$ gcc -std=gnu99 -Wall -Werror -pedantic -fopenmp parallel-sum-openmp.c -lrt && /usr/bin/time ./a.out
*/
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
double perf_counter() {
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tp) < 0) {
perror("clock_gettime");
abort();
}
return tp.tv_sec + tp.tv_nsec * 1e-9;
}
int main() {
int a[] = {
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17
};
intmax_t sum = 0;
double start = perf_counter();
#pragma omp parallel for reduction(+:sum)
for (size_t n = 0; n < 1000000; ++n)
for (size_t i = 0; i < (sizeof(a) / sizeof(*a)); ++i)
sum += a[i];
printf("got sum: %" PRIiMAX " in %.2f seconds\n",
sum, perf_counter() - start);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment