From bbaf5dab2bbc060332d18c663e1c404d1d0e0e2e Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Sun, 19 Aug 2018 20:52:56 +0200 Subject: remove conprod benchmark because it doesn't measure malloc performance --- Makefile | 5 -- bench_conprod.py | 155 ------------------------------------------ benchmarks/bench_conprod.c | 165 --------------------------------------------- 3 files changed, 325 deletions(-) delete mode 100644 bench_conprod.py delete mode 100644 benchmarks/bench_conprod.c 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 -#include -#include -#include -#include -#include -#include - -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 \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; -} -- cgit v1.2.3