diff options
author | Benji Dial <benji@benjidial.net> | 2023-05-30 21:39:37 -0400 |
---|---|---|
committer | Benji Dial <benji@benjidial.net> | 2023-05-30 21:39:37 -0400 |
commit | 6b2cbe6c00c1b008e3145c1adf6096640f4e7bbd (patch) | |
tree | 6c53b7bdc207f7acb024ccdcec64ca2c64211050 | |
parent | 82699138982bf177366c52757e888d7ca3f04b66 (diff) | |
download | lib94-6b2cbe6c00c1b008e3145c1adf6096640f4e7bbd.tar.gz |
template single_step and executors on whether to update address sets to improve performance in non-gui programs
-rw-r--r-- | bench/bench_window.cpp | 2 | ||||
-rw-r--r-- | include/lib94/lib94.hpp | 1 | ||||
-rw-r--r-- | lib94/core.cpp | 72 | ||||
-rw-r--r-- | lib94/executors.cpp | 109 | ||||
-rw-r--r-- | score/main.cpp | 2 | ||||
-rw-r--r-- | tabulator-mpi/worker.cpp | 2 |
6 files changed, 102 insertions, 86 deletions
diff --git a/bench/bench_window.cpp b/bench/bench_window.cpp index 767198b..7393e9f 100644 --- a/bench/bench_window.cpp +++ b/bench/bench_window.cpp @@ -115,7 +115,7 @@ const lib94::warrior *bench_window::do_step() { last_core_step_distance = time - last_core_step_start; last_core_step_start = time; - const lib94::warrior *result = lib94::single_step(); + const lib94::warrior *result = lib94::single_step<true>(); core.mut.lock(); core.age_all(); diff --git a/include/lib94/lib94.hpp b/include/lib94/lib94.hpp index eeb53ec..18f90b4 100644 --- a/include/lib94/lib94.hpp +++ b/include/lib94/lib94.hpp @@ -92,6 +92,7 @@ namespace lib94 { //assumes that there is a next warrior //returns a warrior if it dies + template <bool update_address_sets> const warrior *single_step(); } diff --git a/lib94/core.cpp b/lib94/core.cpp index 49b76e5..a19e6b7 100644 --- a/lib94/core.cpp +++ b/lib94/core.cpp @@ -48,10 +48,6 @@ namespace lib94 { read_addresses.insert(instr - core); } - void add_executed_instruction(const instruction *instr) { - executed_addresses.insert(instr - core); - } - struct warrior_info { const warrior *the_warrior; std::deque<number_t> processes; @@ -226,37 +222,42 @@ namespace lib94 { } } - template<opcode op, modifier mod> + template<opcode op, modifier mod, bool uas> bool execute(); - #define EXECUTOR_DECL_LINE(mod) \ - extern template bool execute<DAT, mod>(); extern template bool execute<MOV, mod>(); \ - extern template bool execute<ADD, mod>(); extern template bool execute<SUB, mod>(); \ - extern template bool execute<MUL, mod>(); extern template bool execute<DIV, mod>(); \ - extern template bool execute<MOD, mod>(); extern template bool execute<JMP, mod>(); \ - extern template bool execute<JMZ, mod>(); extern template bool execute<JMN, mod>(); \ - extern template bool execute<DJN, mod>(); extern template bool execute<SEQ, mod>(); \ - extern template bool execute<SNE, mod>(); extern template bool execute<SLT, mod>(); \ - extern template bool execute<SPL, mod>(); extern template bool execute<NOP, mod>(); - - EXECUTOR_DECL_LINE(A) - EXECUTOR_DECL_LINE(B) - EXECUTOR_DECL_LINE(AB) - EXECUTOR_DECL_LINE(BA) - EXECUTOR_DECL_LINE(F) - EXECUTOR_DECL_LINE(X) - EXECUTOR_DECL_LINE(I) + #define EXECUTOR_DECL_LINE(mod, uas) \ + extern template bool execute<DAT, mod, uas>(); extern template bool execute<MOV, mod, uas>(); \ + extern template bool execute<ADD, mod, uas>(); extern template bool execute<SUB, mod, uas>(); \ + extern template bool execute<MUL, mod, uas>(); extern template bool execute<DIV, mod, uas>(); \ + extern template bool execute<MOD, mod, uas>(); extern template bool execute<JMP, mod, uas>(); \ + extern template bool execute<JMZ, mod, uas>(); extern template bool execute<JMN, mod, uas>(); \ + extern template bool execute<DJN, mod, uas>(); extern template bool execute<SEQ, mod, uas>(); \ + extern template bool execute<SNE, mod, uas>(); extern template bool execute<SLT, mod, uas>(); \ + extern template bool execute<SPL, mod, uas>(); extern template bool execute<NOP, mod, uas>(); + + #define EXECUTOR_DECL(uas) \ + EXECUTOR_DECL_LINE(A, uas) \ + EXECUTOR_DECL_LINE(B, uas) \ + EXECUTOR_DECL_LINE(AB, uas) \ + EXECUTOR_DECL_LINE(BA, uas) \ + EXECUTOR_DECL_LINE(F, uas) \ + EXECUTOR_DECL_LINE(X, uas) \ + EXECUTOR_DECL_LINE(I, uas) + + EXECUTOR_DECL(true) + EXECUTOR_DECL(false) #define EXECUTOR_REF_LINE(mod) \ - &execute<DAT, mod>, &execute<MOV, mod>, \ - &execute<ADD, mod>, &execute<SUB, mod>, \ - &execute<MUL, mod>, &execute<DIV, mod>, \ - &execute<MOD, mod>, &execute<JMP, mod>, \ - &execute<JMZ, mod>, &execute<JMN, mod>, \ - &execute<DJN, mod>, &execute<SEQ, mod>, \ - &execute<SNE, mod>, &execute<SLT, mod>, \ - &execute<SPL, mod>, &execute<NOP, mod> - + &execute<DAT, mod, uas>, &execute<MOV, mod, uas>, \ + &execute<ADD, mod, uas>, &execute<SUB, mod, uas>, \ + &execute<MUL, mod, uas>, &execute<DIV, mod, uas>, \ + &execute<MOD, mod, uas>, &execute<JMP, mod, uas>, \ + &execute<JMZ, mod, uas>, &execute<JMN, mod, uas>, \ + &execute<DJN, mod, uas>, &execute<SEQ, mod, uas>, \ + &execute<SNE, mod, uas>, &execute<SLT, mod, uas>, \ + &execute<SPL, mod, uas>, &execute<NOP, mod, uas> + + template <bool uas> static const std::function<bool ()> executors[] = { EXECUTOR_REF_LINE(A), EXECUTOR_REF_LINE(B), EXECUTOR_REF_LINE(AB), EXECUTOR_REF_LINE(BA), @@ -270,6 +271,7 @@ namespace lib94 { this_warrior->processes.push_back(pc); } + template <bool update_address_sets> const warrior *single_step() { this_warrior = alive_warriors.front(); alive_warriors.pop_front(); @@ -277,7 +279,8 @@ namespace lib94 { program_counter = this_warrior->processes.front(); this_warrior->processes.pop_front(); - executed_addresses.insert(program_counter); + if constexpr (update_address_sets) + executed_addresses.insert(program_counter); instruction_register = core[program_counter]; evaluate_operand(instruction_register.amode, instruction_register.anumber, a_pointer, a_instruction); @@ -286,7 +289,7 @@ namespace lib94 { a_instruction_writable = core + (program_counter + a_pointer) % LIB94_CORE_SIZE; b_instruction_writable = core + (program_counter + b_pointer) % LIB94_CORE_SIZE; - bool should_endeque = executors[instruction_register.op + instruction_register.mod * 16](); + bool should_endeque = executors<update_address_sets>[instruction_register.op + instruction_register.mod * 16](); if (should_endeque) this_warrior->processes.push_back((program_counter + 1) % LIB94_CORE_SIZE); @@ -298,4 +301,7 @@ namespace lib94 { return 0; } + template const warrior *single_step<true>(); + template const warrior *single_step<false>(); + } diff --git a/lib94/executors.cpp b/lib94/executors.cpp index 236944b..12b371c 100644 --- a/lib94/executors.cpp +++ b/lib94/executors.cpp @@ -17,6 +17,11 @@ namespace lib94 { void add_written_instruction(const instruction *instr); void add_read_instruction(const instruction *instr); + #define maybe_add_written_instruction(instr) \ + if constexpr (uas) add_written_instruction(instr) + #define maybe_add_read_instruction(instr) \ + if constexpr (uas) add_read_instruction(instr) + struct single_target { number_t *ptr; @@ -154,7 +159,7 @@ namespace lib94 { template<> struct target<X> : pair_target {}; template<> struct target<I> : instruction_target {}; - template<opcode op, modifier mod> + template<opcode op, modifier mod, bool uas> bool execute() { target<mod> dest_out; target<mod> dest_in; @@ -214,8 +219,8 @@ namespace lib94 { return false; else if constexpr (op == MOV) { - add_read_instruction(a_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); if constexpr (mod == I) { dest_out.instr->op = src_in.instr->op; dest_out.instr->mod = src_in.instr->mod; @@ -229,36 +234,36 @@ namespace lib94 { } else if constexpr (op == ADD) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); return dest_out.assign(dest_in, src_in, [](number_t a, number_t b) -> std::optional<number_t> { return (a + b) % LIB94_CORE_SIZE; }); } else if constexpr (op == SUB) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); return dest_out.assign(dest_in, src_in, [](number_t a, number_t b) -> std::optional<number_t> { return (a + LIB94_CORE_SIZE - b) % LIB94_CORE_SIZE; }); } else if constexpr (op == MUL) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); return dest_out.assign(dest_in, src_in, [](number_t a, number_t b) -> std::optional<number_t> { return (a * b) % LIB94_CORE_SIZE; }); } else if constexpr (op == DIV) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); return dest_out.assign(dest_in, src_in, [](number_t a, number_t b) -> std::optional<number_t> { if (b == 0) return {}; @@ -267,9 +272,9 @@ namespace lib94 { } else if constexpr (op == MOD) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); return dest_out.assign(dest_in, src_in, [](number_t a, number_t b) -> std::optional<number_t> { if (b == 0) return {}; @@ -278,62 +283,62 @@ namespace lib94 { } else if constexpr (op == JMP) { - add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); program_counter = (a_instruction_writable - core + LIB94_CORE_SIZE - 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == JMZ) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); if (dest_in.is_zero()) program_counter = (a_instruction_writable - core + LIB94_CORE_SIZE - 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == JMN) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); if (!dest_in.is_zero()) program_counter = (a_instruction_writable - core + LIB94_CORE_SIZE - 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == DJN) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); - add_written_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); + maybe_add_written_instruction(b_instruction_writable); if (dest_out.dec_not_zero()) program_counter = (a_instruction_writable - core + LIB94_CORE_SIZE - 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == SEQ) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); if (src_in.equal_to(dest_in)) program_counter = (program_counter + 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == SNE) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); if (!src_in.equal_to(dest_in)) program_counter = (program_counter + 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == SLT) { - add_read_instruction(a_instruction_writable); - add_read_instruction(b_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(b_instruction_writable); if (src_in.less_than(dest_in)) program_counter = (program_counter + 1) % LIB94_CORE_SIZE; return true; } else if constexpr (op == SPL) { - add_read_instruction(a_instruction_writable); + maybe_add_read_instruction(a_instruction_writable); enqueue_process((program_counter + 1) % LIB94_CORE_SIZE); program_counter = (a_instruction_writable - core + LIB94_CORE_SIZE - 1) % LIB94_CORE_SIZE; return true; @@ -345,22 +350,26 @@ namespace lib94 { else assert(false); } - #define EXECUTOR_INST_LINE(mod) \ - template bool execute<DAT, mod>(); template bool execute<MOV, mod>(); \ - template bool execute<ADD, mod>(); template bool execute<SUB, mod>(); \ - template bool execute<MUL, mod>(); template bool execute<DIV, mod>(); \ - template bool execute<MOD, mod>(); template bool execute<JMP, mod>(); \ - template bool execute<JMZ, mod>(); template bool execute<JMN, mod>(); \ - template bool execute<DJN, mod>(); template bool execute<SEQ, mod>(); \ - template bool execute<SNE, mod>(); template bool execute<SLT, mod>(); \ - template bool execute<SPL, mod>(); template bool execute<NOP, mod>(); - - EXECUTOR_INST_LINE(A) - EXECUTOR_INST_LINE(B) - EXECUTOR_INST_LINE(AB) - EXECUTOR_INST_LINE(BA) - EXECUTOR_INST_LINE(F) - EXECUTOR_INST_LINE(X) - EXECUTOR_INST_LINE(I) + #define EXECUTOR_INST_LINE(mod, uas) \ + template bool execute<DAT, mod, uas>(); template bool execute<MOV, mod, uas>(); \ + template bool execute<ADD, mod, uas>(); template bool execute<SUB, mod, uas>(); \ + template bool execute<MUL, mod, uas>(); template bool execute<DIV, mod, uas>(); \ + template bool execute<MOD, mod, uas>(); template bool execute<JMP, mod, uas>(); \ + template bool execute<JMZ, mod, uas>(); template bool execute<JMN, mod, uas>(); \ + template bool execute<DJN, mod, uas>(); template bool execute<SEQ, mod, uas>(); \ + template bool execute<SNE, mod, uas>(); template bool execute<SLT, mod, uas>(); \ + template bool execute<SPL, mod, uas>(); template bool execute<NOP, mod, uas>(); + + #define EXECUTOR_INST(uas) \ + EXECUTOR_INST_LINE(A, uas) \ + EXECUTOR_INST_LINE(B, uas) \ + EXECUTOR_INST_LINE(AB, uas) \ + EXECUTOR_INST_LINE(BA, uas) \ + EXECUTOR_INST_LINE(F, uas) \ + EXECUTOR_INST_LINE(X, uas) \ + EXECUTOR_INST_LINE(I, uas) + + EXECUTOR_INST(true) + EXECUTOR_INST(false) } diff --git a/score/main.cpp b/score/main.cpp index fa646d0..aae9ba2 100644 --- a/score/main.cpp +++ b/score/main.cpp @@ -85,7 +85,7 @@ int main(int argc, const char **argv) { for (unsigned step_number = 0; step_number < steps_until_tie; ++step_number) { - const lib94::warrior *w = lib94::single_step(); + const lib94::warrior *w = lib94::single_step<false>(); if (w == ws[0]) { ++w2_wins; diff --git a/tabulator-mpi/worker.cpp b/tabulator-mpi/worker.cpp index e9768b2..47b8eeb 100644 --- a/tabulator-mpi/worker.cpp +++ b/tabulator-mpi/worker.cpp @@ -15,7 +15,7 @@ static int do_round(const lib94::warrior *w1, const lib94::warrior *w2) { lib94::init_round(ws, 2); for (int i = 0; i < 1000000; ++i) { - const lib94::warrior *result = lib94::single_step(); + const lib94::warrior *result = lib94::single_step<false>(); if (result == w1) return -1; if (result == w2) |