Skip to content

Commit 8c55c7a

Browse files
committed
pthread_array_sum
1 parent 4f8d6e3 commit 8c55c7a

11 files changed

+191
-45
lines changed

cpp/thread_return_value.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@
77
#include <cassert>
88
#include <future>
99
#include <iostream>
10-
#include <mutex>
1110
#include <thread>
1211
#include <vector>
1312

14-
std::mutex mutex;
15-
1613
int myfunc(int i) {
1714
return i + 1;
1815
}

posix/README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
1. [pthread_mutex](pthread_mutex.c)
2525
1. [pthread_tid](pthread_tid.c)
2626
1. [pthread_deadlock](pthread_deadlock.c)
27+
1. [pthread array sym](interactive/pthread_array_sum.c)
28+
1. [pthread CPU heavy work](interactive/pthread_cpu_heavy_work.c)
2729
1. [Regex](regex.c)
2830
1. File IO
2931
1. [write_read](write_read.c)
@@ -49,7 +51,6 @@
4951
1. [signal_fork](interactive/signal_fork.c)
5052
1. Interactive
5153
1. [poll](interactive/poll.c)
52-
1. [pthread_work](interactive/pthread_work.c)
5354
1. [sleep cout](interactive/sleep_count.c)
5455
1. [sleep_1](interactive/sleep_1.c)
5556
1. Process information

posix/interactive/pthread_array_sum.c

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/* POSIX version of: https://github.com/cirosantilli/algorithm-cheat/blob/c8489f41c059971008337500013cd9cdf8e86a76/src/cpp/interactive/sum_array_parallel.cpp */
2+
3+
#define _XOPEN_SOURCE 700
4+
#include <assert.h>
5+
#include <inttypes.h>
6+
#include <pthread.h>
7+
#include <stdio.h>
8+
#include <stdlib.h>
9+
#include <unistd.h>
10+
11+
typedef uint64_t DataType;
12+
13+
/* Single threaded array sum. */
14+
DataType sum_array(
15+
DataType *begin,
16+
DataType *end
17+
) {
18+
DataType sum = 0;
19+
while (begin != end) {
20+
sum += *begin;
21+
begin++;
22+
}
23+
return sum;
24+
}
25+
26+
typedef struct {
27+
DataType *begin;
28+
DataType *end;
29+
DataType output;
30+
} SumArrayThreadData;
31+
32+
/* Thread interface. */
33+
void* sum_array_thread(void *arg) {
34+
SumArrayThreadData *thread_data = (SumArrayThreadData*)arg;
35+
DataType *begin = thread_data->begin;
36+
DataType *end = thread_data->end;
37+
thread_data->output = sum_array(begin, end);
38+
return NULL;
39+
}
40+
41+
/* Parallel array sum. */
42+
DataType sum_array_parallel(
43+
DataType *begin,
44+
DataType *end,
45+
long nthreads
46+
) {
47+
size_t array_size = end - begin;
48+
if (array_size < (size_t)nthreads) {
49+
nthreads = array_size;
50+
}
51+
size_t delta = array_size / nthreads;
52+
pthread_t *threads = malloc(nthreads * sizeof(pthread_t));
53+
SumArrayThreadData *thread_datas = malloc(nthreads * sizeof(SumArrayThreadData));
54+
for (long i = 0; i < nthreads; ++i) {
55+
thread_datas[i].begin = begin;
56+
thread_datas[i].end = begin + delta;
57+
assert(!pthread_create(
58+
&threads[i],
59+
NULL,
60+
sum_array_thread,
61+
(void*)&thread_datas[i]
62+
));
63+
begin += delta;
64+
}
65+
DataType sum = 0;
66+
for (long i = 0; i < nthreads; ++i) {
67+
assert(!pthread_join(threads[i], NULL));
68+
sum += thread_datas[i].output;
69+
}
70+
free(threads);
71+
free(thread_datas);
72+
return sum + sum_array(begin, end);
73+
}
74+
75+
void print_result(
76+
unsigned int nthreads,
77+
struct timespec *tstart,
78+
struct timespec *tend
79+
) {
80+
printf(
81+
"%d %.4f\n",
82+
nthreads,
83+
(
84+
((double)tend->tv_sec + 1.0e-9 * tend->tv_nsec) -
85+
((double)tstart->tv_sec + 1.0e-9 * tstart->tv_nsec)
86+
)
87+
);
88+
}
89+
90+
int main(int argc, char **argv) {
91+
unsigned long long array_size;
92+
struct timespec tstart, tend;
93+
94+
/* Handle CLI arguments. */
95+
if (argc > 1) {
96+
array_size = strtoll(argv[1], NULL, 10);
97+
} else {
98+
array_size = 10;
99+
}
100+
101+
/* Initialize array with random numbers. */
102+
DataType *array = malloc(sizeof(DataType) * array_size);
103+
assert(array);
104+
srand(time(NULL));
105+
for (size_t i = 0; i < array_size; ++i) {
106+
array[i] = rand();
107+
}
108+
109+
/* Output header. */
110+
printf("nthreads elapsed_time_seconds\n");
111+
112+
/* Single threaded sanity check. */
113+
clock_gettime(CLOCK_MONOTONIC, &tstart);
114+
DataType serial_result = sum_array(array, array + array_size);
115+
clock_gettime(CLOCK_MONOTONIC, &tend);
116+
print_result(0, &tstart, &tend);
117+
118+
/* Use different number of threads. */
119+
long max_nthreads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
120+
for (long nthreads = 1; nthreads <= max_nthreads; ++nthreads) {
121+
clock_gettime(CLOCK_MONOTONIC, &tstart);
122+
DataType result = sum_array_parallel(array, array + array_size, nthreads);
123+
clock_gettime(CLOCK_MONOTONIC, &tend);
124+
print_result(nthreads, &tstart, &tend);
125+
/* Sanity check that our implementation is correct. */
126+
assert(result == serial_result);
127+
}
128+
129+
/* Cleanup. */
130+
free(array);
131+
return EXIT_SUCCESS;
132+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env gnuplot
2+
set terminal png size 1024, 1024
3+
set style data linespoints
4+
set key autotitle columnhead
5+
set output 'pthread_array_sum.png'
6+
set title "Array sum time elapsed in function of threads"
7+
set xlabel "threads"
8+
set ylabel "time (s)"
9+
plot 'pthread_array_sum.dat' using 1:2 notitle
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env bash
2+
set -eu
3+
make -B O=3 pthread_array_sum.out
4+
./pthread_array_sum.out 1000000000 | tee pthread_array_sum.dat
5+
./pthread_array_sum.gnuplot

posix/interactive/pthread_count.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
/* To see if
1+
/* Launch some very long running threads.
2+
*
3+
* Initial motivation: confirm that:
24
*
35
* ./pthread_count.out &
46
* cat /proc/$!/status | grep -E '^Threads:'
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/usr/bin/env gnuplot
2+
set terminal png size 1024, 1024
3+
set style data linespoints
4+
set output 'pthread_cpu_heavy_work.png'
5+
set multiplot layout 3,1
6+
set xlabel "threads"
7+
8+
set title "wall, user and sys"
9+
set ylabel "time (s)"
10+
set yrange [-20:]
11+
set key right center
12+
plot 'pthread_cpu_heavy_work.dat' using 1:2 title 'wall', \
13+
'pthread_cpu_heavy_work.dat' using 1:3 title 'user', \
14+
'pthread_cpu_heavy_work.dat' using 1:4 title 'sys'
15+
16+
set title "wall, user and sys / threads"
17+
set yrange [0:]
18+
set key right top
19+
plot 'pthread_cpu_heavy_work.dat' using 1:($2/$1) title 'wall', \
20+
'pthread_cpu_heavy_work.dat' using 1:($3/$1) title 'user', \
21+
'pthread_cpu_heavy_work.dat' using 1:($4/$1) title 'sys'
22+
23+
set title 'user / wall ratio'
24+
set ylabel "ratio"
25+
set yrange [0:*]
26+
plot 'pthread_cpu_heavy_work.dat' using 1:($3/$2) notitle
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env bash
2+
i=1
3+
n="$(($(nproc) * 2))"
4+
rm -f pthread_cpu_heavy_work.dat
5+
while [ "$i" -le "$n" ]; do
6+
env time \
7+
--append \
8+
--format "$i %e %U %S" \
9+
--output pthread_cpu_heavy_work.dat \
10+
./pthread_cpu_heavy_work.out 10000000000 "$i" \
11+
;
12+
i=$((i + 1))
13+
done
14+
./pthread_cpu_heavy_work.gnuplot

posix/interactive/pthread_work.gnuplot

-26
This file was deleted.

posix/interactive/pthread_work.sh

-14
This file was deleted.

0 commit comments

Comments
 (0)