summaryrefslogtreecommitdiff
path: root/sim.h
diff options
context:
space:
mode:
authorJohn Fultz <jfultz@wolfram.com>2019-03-19 11:21:46 -0500
committerJohn Fultz <jfultz@wolfram.com>2019-07-21 02:02:55 -0700
commitf2e42335d294128591fb123baddf7182ca390d40 (patch)
tree779931ce5c0963862fd4c870516045549149073c /sim.h
parente7f645d4f5030e52b1c9f27dc3fbf2c20fd47cd5 (diff)
Sims are now threaded.
Defaults to two threads right now. This can be changed in the Simulator constructor for the time being. An interface will be added for this soon. For an example I tried, I got the following times on 500 simulations in a macOS release build: * Quackle 1.0.3 - 26 seconds * master branch, 1 thread - 27 seconds * master branch, 2 threads - 19 seconds * master branch, 4 threads - 15 seconds This isn't the most efficient use of threads. It distributes all of the plays being simmed into a thread pool, but only for one simulation. Then it comes up for air and tries again. This was the easiest to implement robustly given the current architecture.
Diffstat (limited to 'sim.h')
-rw-r--r--sim.h39
1 files changed, 39 insertions, 0 deletions
diff --git a/sim.h b/sim.h
index ff618ef..6c66121 100644
--- a/sim.h
+++ b/sim.h
@@ -20,7 +20,11 @@
#define QUACKLE_SIM_H
#include <atomic>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
#include <sstream>
+#include <thread>
#include <vector>
#include "alphabetparameters.h"
@@ -201,11 +205,38 @@ public:
bool isLogging;
};
+class SimmedMoveMessageQueue
+{
+public:
+ SimmedMoveMessageQueue() = default;
+ SimmedMoveMessageQueue(SimmedMoveMessageQueue&) = delete;
+ SimmedMoveMessageQueue(SimmedMoveMessageQueue&&) = delete;
+
+ void push(SimmedMoveMessage& msg);
+ SimmedMoveMessage pop();
+ std::pair<SimmedMoveMessage, bool> pop_or_terminate();
+ void send_terminate_all();
+ void send_terminate_one(const std::thread::id& id);
+
+ const SimmedMoveConstants& constants() { return m_constants; };
+ void setConstants(const SimmedMoveConstants& constants) { m_constants = constants; };
+
+private:
+ SimmedMoveConstants m_constants;
+ std::queue<SimmedMoveMessage> m_queue;
+ std::condition_variable m_condition;
+ std::mutex m_queueMutex;
+ bool m_terminateAll = false;
+ std::thread::id m_terminateOne;
+};
+
class Simulator
{
public:
// constructs a new simulator
Simulator();
+ Simulator(const Simulator&) = delete;
+ Simulator(Simulator&&) = delete;
~Simulator();
// Simulate moves on this position. Also initializes the
@@ -263,6 +294,9 @@ public:
void setIgnoreOppos(bool ignore);
bool ignoreOppos() const;
+ static void simThreadFunc(SimmedMoveMessageQueue& incoming, SimmedMoveMessageQueue& outgoing);
+ void setThreadCount(size_t count);
+
// set values for all levels of all moves to zero
void resetNumbers();
@@ -337,6 +371,11 @@ protected:
int m_iterations;
bool m_ignoreOppos;
+
+ // Pair of thread and bool requesting to terminate
+ std::vector<std::thread> m_threadPool;
+ SimmedMoveMessageQueue m_sendQueue;
+ SimmedMoveMessageQueue m_receiveQueue;
};
inline GamePosition &Simulator::currentPosition()