From 21d9e26dfb72ba6d0fa4f3f40a439e51d943d349 Mon Sep 17 00:00:00 2001 From: Jan Huwald Date: Mon, 24 Jun 2013 11:20:54 +0200 Subject: support canceling iterTrans if no work is done anymore A bool is passed to the worker function to store wether any work has been done in an iterState round. To prevent cache line bouncing, each worker thread has its own cache line aligned bool which is ultimately merged. diff --git a/cachepad.hpp b/cachepad.hpp new file mode 100644 index 0000000..beb7528 --- /dev/null +++ b/cachepad.hpp @@ -0,0 +1,15 @@ +#pragma once + +template +struct cache_pad { + template + cache_pad(Arg... args) : val(args...) {} + + operator T () { return val; } + T& operator () () { return val; } + + union { + T val; + char pad[(sizeof(T) + 63) / 64 * 64]; + }; +} __attribute__ ((aligned (64))); // TODO: port to C++11 alignas once GCC support is old enough diff --git a/cacount.cpp b/cacount.cpp index 882e4a6..f135936 100644 --- a/cacount.cpp +++ b/cacount.cpp @@ -12,6 +12,7 @@ #include #include +#include "cachepad.hpp" #include "mmalloc.hpp" #include "timer.hpp" @@ -44,31 +45,43 @@ State update(State s) { typedef array Trans; typedef array pbitset; -void iterState(function f, optional msg = optional(), bool parallel = false) { +bool iterStateP(function f, optional msg = optional(), bool parallel = false, bool skipWorkTest = false) { PerfPrinter perfPrinter(msg); - int numThreads=1; - if (parallel) { + int numThreads = 1; + if (parallel) numThreads = min(thread::hardware_concurrency(), numState); - } + cache_pad *perThreadWorked = new cache_pad[numThreads]; list tasks; for (int t=0; tjoin(), delete tasks.front(), tasks.pop_front()); + for (; !tasks.empty(); tasks.front()->join(), delete tasks.front(), tasks.pop_front()); + bool worked = skipWorkTest; + for (int t=0; t f, optional msg = optional(), bool parallel = false) { + return iterStateP([=](State s, bool &) { f(s); }, msg, parallel, true); } -void iterTrans(int times, function f, optional msg = optional(), bool parallel = false) { +void iterTransP(int times, function f, optional msg = optional(), bool parallel = false, bool skipWorkTest = false) { PerfPrinter perfPrinter(msg); auto msg2 = [=,&msg] (int i) { return msg ? (*msg + string(" ") + to_string(times-i) + string("/") + to_string(times)) : msg; }; - while (times--) { - iterState(f, msg2(times), parallel); - } + while (times--) + if (not iterStateP(f, msg2(times), parallel, skipWorkTest)) return; +} + +void iterTrans(int times, function f, optional msg = optional(), bool parallel = false) { + iterTransP(times, [=](State s, bool &) { f(s); }, msg, parallel, true); } void init(Trans &t, Trans &c, pbitset &reachable) { -- cgit v0.10.1