aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--bench_conprod.py155
-rw-r--r--benchmarks/bench_conprod.c165
3 files changed, 0 insertions, 325 deletions
diff --git a/Makefile b/Makefile
index 05e04da..fa40390 100644
--- a/Makefile
+++ b/Makefile
@@ -46,11 +46,6 @@ $(OBJDIR)/cache-scratch: $(OBJDIR)/cache-scratch.o
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
$(VERBOSE) $(CXX) -pthread -o $@ $^
-$(OBJDIR)/bench_conprod: $(OBJDIR)/bench_conprod.o
- @echo "ld $@"
- @if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
- $(VERBOSE) $(CC) -pthread -o $@ $^
-
$(OBJDIR)/bench_loop: $(OBJDIR)/bench_loop.o
@echo "ld $@"
@if test \( ! \( -d $(@D) \) \) ;then mkdir -p $(@D);fi
diff --git a/bench_conprod.py b/bench_conprod.py
deleted file mode 100644
index 98a3a84..0000000
--- a/bench_conprod.py
+++ /dev/null
@@ -1,155 +0,0 @@
-import csv
-import pickle
-import matplotlib.pyplot as plt
-import multiprocessing
-import numpy as np
-import os
-import subprocess
-
-from benchmark import Benchmark
-from common_targets import common_targets
-
-cmd = ("perf stat -x\; -e cpu-clock:k,cache-references,cache-misses,cycles,"
- "instructions,branches,faults,migrations "
- "build/bench_conprod{0} {1} {1} {1} 1000000 {2}")
-
-class Benchmark_ConProd( Benchmark ):
- def __init__(self):
- self.file_name = "bench_conprod"
- self.name = "Consumer Producer Stress Benchmark"
- self.descrition = """This benchmark makes 1000000 allocations in each of
- n producer threads. The allocations are shared through n
- synchronisation objects and freed/consumed by n threads."""
- self.targets = common_targets
- self.maxsize = [2 ** x for x in range(6, 16)]
- self.nthreads = range(1, multiprocessing.cpu_count() + 1)
-
- self.results = {"args" : {"nthreads" : self.nthreads, "maxsize" : self.maxsize},
- "targets" : self.targets}
-
- def prepare(self, verbose=False):
- req = ["build/bench_conprod"]
- for r in req:
- if not os.path.isfile(r):
- print(r, "not found")
- return False
- if not os.access(r, os.X_OK):
- print(r, "not found")
- return False
- if verbose:
- print(r, "found and executable.")
- return True
-
- def run(self, verbose=False, runs=3):
- args_permutations = [(x,y) for x in self.nthreads for y in self.maxsize]
- n = len(args_permutations)
- for run in range(1, runs + 1):
- print(str(run) + ". run")
-
- for i, args in enumerate(args_permutations):
- print(i + 1, "of", n, "\r", end='')
-
- # run cmd for each target
- for tname, t in self.targets.items():
- result = {"VSZ" : [] , "RSS" : []}
-
- os.environ["LD_PRELOAD"] = t[1]
-
- target_cmd = cmd.format(t[0], *args).split(" ")
- if verbose:
- print("\n" + tname, t, "\n", " ".join(target_cmd), "\n")
-
- p = subprocess.Popen(target_cmd,
- env=os.environ,
- stderr=subprocess.PIPE,
- stdout=subprocess.PIPE,
- universal_newlines=True)
-
- while p.poll() == None:
- ps = subprocess.run(["ps", "-F", "--ppid", str(p.pid)], stdout=subprocess.PIPE)
- lines = ps.stdout.splitlines()
- if len(lines) == 1: # perf hasn't forked yet
- continue
- tokens = str(lines[1]).split()
- result["VSZ"].append(tokens[4])
- result["RSS"].append(tokens[5])
-
- p.wait()
-
- output = p.stderr.read()
-
- if p.returncode != 0:
- print("\n" + " ".join(target_cmd), "exited with", p.returncode, ".\n Aborting Benchmark.")
- print(tname, t)
- print(p.stderr)
- print(output)
- return False
-
- if "ERROR: ld.so" in output:
- print("\nPreloading of", t[1], "failed for", tname, ".\n Aborting Benchmark.")
- print(output)
- return False
-
- # Handle perf output
- csvreader = csv.reader(output.splitlines(), delimiter=';')
- for row in csvreader:
- result[row[2].replace("\\", "")] = row[0].replace("\\", "")
- key = (tname, *args)
- if not key in self.results:
- self.results[key] = [result]
- else:
- self.results[key].append(result)
-
- print()
- return True
-
- def summary(self):
- # MAXSIZE fixed
- nthreads = self.results["args"]["nthreads"]
- maxsize = self.results["args"]["maxsize"]
- targets = self.results["targets"]
-
- y_mapping = {v : i for i, v in enumerate(nthreads)}
- for size in maxsize:
- for target in targets:
- y_vals = [0] * len(nthreads)
- for mid, measures in self.results.items():
- if mid[0] == target and mid[2] == size:
- d = []
- for m in measures:
- # nthreads/time = MOPS/S
- d.append(mid[1]/float(m["cpu-clock:ku"]))
- y_vals[y_mapping[mid[1]]] = np.mean(d)
- plt.plot(nthreads, y_vals, label=target, linestyle='-', marker='.')
-
- plt.legend()
- plt.xlabel("consumers/producers")
- plt.ylabel("MOPS/s")
- plt.title("Consumer Producer: " + str(size) + "B")
- plt.savefig(self.file_name + "." + str(size) + "B.png")
- plt.clf()
-
- # NTHREADS fixed
- y_mapping = {v : i for i, v in enumerate(maxsize)}
- x_vals = [i + 1 for i in range(0, len(maxsize))]
- for n in nthreads:
- for target in targets:
- y_vals = [0] * len(maxsize)
- for mid, measures in self.results.items():
- if mid[0] == target and mid[1] == n:
- d = []
- for m in measures:
- # nthreads/time = MOPS/S
- d.append(n/float(m["cpu-clock:ku"]))
- y_vals[y_mapping[mid[2]]] = np.mean(d)
- plt.plot(x_vals, y_vals, label=target, linestyle='-', marker='.')
-
- plt.legend()
- plt.xticks(x_vals, maxsize)
- plt.xlabel("size in B")
- plt.ylabel("MOPS/s")
- plt.title("Consumer Producer: " + str(n) + "thread(s)")
- plt.savefig(self.file_name + "." + str(n) + "thread.png")
- plt.clf()
-
-conprod = Benchmark_ConProd()
diff --git a/benchmarks/bench_conprod.c b/benchmarks/bench_conprod.c
deleted file mode 100644
index 3b349ce..0000000
--- a/benchmarks/bench_conprod.c
+++ /dev/null
@@ -1,165 +0,0 @@
-#include <assert.h>
-#include <malloc.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <semaphore.h>
-
-static size_t _rand() {
- static __thread size_t seed = 123456789;
- size_t a = 1103515245;
- size_t c = 12345;
- size_t m = 1 << 31;
- seed = (a * seed + c) % m;
- return seed;
-}
-
-typedef struct Store {
- pthread_mutex_t mutex;
- sem_t free;
- sem_t avail;
- int toconsum;
- int pos;
- void* ptrs[100];
-} Store;
-
-typedef struct ThreadArgs {
- bool isconsumer;
- Store* store;
- int allocations;
- int maxsize;
-} ThreadArgs;
-
-static void* malloc_then_write(size_t size) {
- void* ptr = malloc(size);
- // Write to ptr
- *((char*)ptr) = '!';
- return ptr;
-}
-
-static void read_then_free(void* ptr) {
- // Read before free
- char s __attribute__((unused)) = *((char*)ptr);
- free(ptr);
-}
-static void* test_thread_func(void* arg) {
- ThreadArgs* args = (ThreadArgs*)arg;
- Store* store = args->store;
-
- if (args->isconsumer)
- {
- while (__sync_sub_and_fetch(&store->toconsum, 1) > -1)
- {
- sem_wait(&store->avail);
- pthread_mutex_lock(&store->mutex);
- void* ptr = store->ptrs[store->pos];
- store->pos--;
- pthread_mutex_unlock(&store->mutex);
- sem_post(&store->free);
- read_then_free(ptr);
- }
- } else {
- for (int i = 0; i < args->allocations; i++)
- {
- void* ptr = malloc_then_write((_rand() % args->maxsize) + 1);
- sem_wait(&store->free);
- pthread_mutex_lock(&store->mutex);
- store->pos++;
- store->ptrs[store->pos] = ptr;
- pthread_mutex_unlock(&store->mutex);
- sem_post(&store->avail);
- }
- }
-
- return NULL;
-}
-
-int main(int argc, char* argv[]) {
- pthread_t* threads;
- int nstores;
- Store* stores;
- int consumers;
- int producers;
- int num_threads;
- int allocations;
- int maxsize;
- struct ThreadArgs* thread_args;
-
- if (argc < 6) {
- fprintf(stderr, "Usage: %s <num stores> <num consumers> <num producers> <num allocations> <max size>\n", argv[0]);
- return 1;
- }
-
- nstores = atoi(argv[1]);
- consumers = atoi(argv[2]);
- if (nstores > consumers)
- {
- fprintf(stderr, "Only %d consumers but %d stores!\n", consumers, nstores);
- }
-
- producers = atoi(argv[3]);
- if (nstores > producers)
- {
- fprintf(stderr, "Only %d producers but %d stores!\n", producers, nstores);
- }
-
- num_threads = consumers + producers;
- allocations = atoi(argv[4]);
- maxsize = atoi(argv[5]);
-
- threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t));
- thread_args = (ThreadArgs*)malloc(num_threads * sizeof(ThreadArgs));
- stores = (Store*)malloc(nstores * sizeof(Store));
- if (threads == 0 || thread_args == 0 || stores == 0)
- {
- perror("malloc");
- return 1;
- }
-
- // Init stores
- for (int i = 0; i < nstores; i++)
- {
- stores[i].pos = -1;
- if (0 != pthread_mutex_init(&stores[i].mutex, 0)) { perror("mutex_init"); return 1; }
- if (0 != sem_init(&stores[i].free, 0, 100)) { perror("sem_init"); return 1; }
- if (0 != sem_init(&stores[i].avail, 0, 0)) { perror("sem_init"); return 1; }
- }
-
- // Build up thread_args
- for (int i = 0; i < num_threads; i++)
- {
- thread_args[i].store = &stores[i % nstores];
- thread_args[i].maxsize = maxsize;
- thread_args[i].allocations = allocations;
-
- if ( i < producers) {
- thread_args[i].isconsumer = false;
- stores[i % nstores].toconsum += allocations;
- } else
- thread_args[i].isconsumer = true;
- }
-
- for (int i = 0; i < num_threads; i++) {
- if (0 != pthread_create(&threads[i], NULL, test_thread_func, &thread_args[i])) {
- perror("pthread_create");
- return 1;
- }
- }
-
- for (int i = 0; i < num_threads; i++) {
- if (0 != pthread_join(threads[i], NULL)) {
- perror("pthread_join");
- return 1;
- }
- }
-
- FILE* f = stdout;
- if (argc == 7)
- f = fopen(argv[6], "w");
- malloc_info(0, f);
- if (argc == 7)
- fclose(f);
-
- return 0;
-}