evoasm 0.0.2.pre7 → 0.1.0.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gdbinit +41 -0
- data/.gitignore +1 -2
- data/.gitmodules +3 -0
- data/.rubocop.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.md +660 -0
- data/Makefile +1 -1
- data/README.md +17 -9
- data/Rakefile +39 -107
- data/bin/gdb +1 -1
- data/bin/gdb_loop +4 -0
- data/docs/FindingInstructions.md +17 -0
- data/docs/JIT.md +14 -0
- data/docs/SymbolicRegression.md +102 -0
- data/docs/Visualization.md +29 -0
- data/docs/examples/bit_insts.rb +44 -0
- data/docs/examples/jit.rb +26 -0
- data/docs/examples/loss.gif +0 -0
- data/docs/examples/program.png +0 -0
- data/docs/examples/sym_reg.rb +64 -0
- data/docs/examples/vis.rb +38 -0
- data/evoasm.gemspec +21 -15
- data/ext/evoasm_ext/Rakefile +3 -0
- data/ext/evoasm_ext/compile.rake +35 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
- data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
- data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
- data/lib/evoasm.rb +28 -11
- data/lib/evoasm/buffer.rb +105 -0
- data/lib/evoasm/capstone.rb +100 -0
- data/lib/evoasm/domain.rb +116 -0
- data/lib/evoasm/error.rb +37 -16
- data/lib/evoasm/exception_error.rb +19 -0
- data/lib/evoasm/ffi_ext.rb +53 -0
- data/lib/evoasm/libevoasm.rb +286 -0
- data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
- data/lib/evoasm/parameter.rb +20 -0
- data/lib/evoasm/population.rb +145 -0
- data/lib/evoasm/population/parameters.rb +227 -0
- data/lib/evoasm/population/plotter.rb +89 -0
- data/lib/evoasm/prng.rb +64 -0
- data/lib/evoasm/program.rb +195 -12
- data/lib/evoasm/program/io.rb +144 -0
- data/lib/evoasm/test.rb +8 -0
- data/lib/evoasm/version.rb +1 -1
- data/lib/evoasm/x64.rb +115 -0
- data/lib/evoasm/x64/cpu_state.rb +95 -0
- data/lib/evoasm/x64/instruction.rb +109 -0
- data/lib/evoasm/x64/operand.rb +156 -0
- data/lib/evoasm/x64/parameters.rb +211 -0
- data/test/helpers/population_helper.rb +128 -0
- data/test/helpers/test_helper.rb +1 -0
- data/test/helpers/x64_helper.rb +24 -0
- data/test/integration/bitwise_reverse_test.rb +41 -0
- data/test/integration/gcd_test.rb +52 -0
- data/test/integration/popcnt_test.rb +46 -0
- data/test/integration/sym_reg_test.rb +68 -0
- data/test/unit/evoasm/buffer_test.rb +48 -0
- data/test/unit/evoasm/capstone_test.rb +18 -0
- data/test/unit/evoasm/domain_test.rb +55 -0
- data/test/unit/evoasm/population/parameters_test.rb +106 -0
- data/test/unit/evoasm/population_test.rb +96 -0
- data/test/unit/evoasm/prng_test.rb +47 -0
- data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
- data/test/unit/evoasm/x64/encoding_test.rb +320 -0
- data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
- data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
- data/test/unit/evoasm/x64/instruction_test.rb +62 -0
- data/test/unit/evoasm/x64/parameters_test.rb +65 -0
- data/test/unit/evoasm/x64_test.rb +52 -0
- metadata +195 -89
- data/Gemfile.rake +0 -8
- data/Gemfile.rake.lock +0 -51
- data/LICENSE.txt +0 -373
- data/data/tables/README.md +0 -19
- data/data/tables/x64.csv +0 -1684
- data/data/templates/evoasm-x64.c.erb +0 -319
- data/data/templates/evoasm-x64.h.erb +0 -126
- data/examples/abs.yml +0 -20
- data/examples/popcnt.yml +0 -17
- data/examples/sym_reg.yml +0 -26
- data/exe/evoasm-search +0 -13
- data/ext/evoasm_ext/evoasm-alloc.c +0 -145
- data/ext/evoasm_ext/evoasm-alloc.h +0 -59
- data/ext/evoasm_ext/evoasm-arch.c +0 -44
- data/ext/evoasm_ext/evoasm-arch.h +0 -161
- data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
- data/ext/evoasm_ext/evoasm-buf.c +0 -130
- data/ext/evoasm_ext/evoasm-buf.h +0 -47
- data/ext/evoasm_ext/evoasm-error.c +0 -31
- data/ext/evoasm_ext/evoasm-error.h +0 -75
- data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
- data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
- data/ext/evoasm_ext/evoasm-log.h +0 -69
- data/ext/evoasm_ext/evoasm-misc.c +0 -23
- data/ext/evoasm_ext/evoasm-misc.h +0 -282
- data/ext/evoasm_ext/evoasm-param.h +0 -37
- data/ext/evoasm_ext/evoasm-search.c +0 -2145
- data/ext/evoasm_ext/evoasm-search.h +0 -214
- data/ext/evoasm_ext/evoasm-util.h +0 -40
- data/ext/evoasm_ext/evoasm-x64.c +0 -275624
- data/ext/evoasm_ext/evoasm-x64.h +0 -5436
- data/ext/evoasm_ext/evoasm.c +0 -7
- data/ext/evoasm_ext/evoasm.h +0 -23
- data/ext/evoasm_ext/evoasm_ext.c +0 -1757
- data/ext/evoasm_ext/extconf.rb +0 -31
- data/lib/evoasm/cli.rb +0 -6
- data/lib/evoasm/cli/search.rb +0 -127
- data/lib/evoasm/core_ext.rb +0 -1
- data/lib/evoasm/core_ext/array.rb +0 -9
- data/lib/evoasm/core_ext/integer.rb +0 -10
- data/lib/evoasm/core_ext/kwstruct.rb +0 -13
- data/lib/evoasm/core_ext/range.rb +0 -5
- data/lib/evoasm/examples.rb +0 -27
- data/lib/evoasm/gen.rb +0 -8
- data/lib/evoasm/gen/enum.rb +0 -169
- data/lib/evoasm/gen/name_util.rb +0 -80
- data/lib/evoasm/gen/state.rb +0 -176
- data/lib/evoasm/gen/state_dsl.rb +0 -152
- data/lib/evoasm/gen/strio.rb +0 -27
- data/lib/evoasm/gen/translator.rb +0 -1102
- data/lib/evoasm/gen/version.rb +0 -5
- data/lib/evoasm/gen/x64.rb +0 -237
- data/lib/evoasm/gen/x64/funcs.rb +0 -495
- data/lib/evoasm/gen/x64/inst.rb +0 -781
- data/lib/evoasm/search.rb +0 -40
- data/lib/evoasm/tasks/gen_task.rb +0 -86
- data/lib/evoasm/tasks/template_task.rb +0 -52
- data/test/test_helper.rb +0 -1
- data/test/x64/test_helper.rb +0 -19
- data/test/x64/x64_test.rb +0 -87
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2016 Julian Aron Prenner <jap@polyadic.com>
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
6
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#include "evoasm-domain.h"
|
|
21
|
+
#include "evoasm-param.h"
|
|
22
|
+
#include "evoasm.h"
|
|
23
|
+
|
|
24
|
+
typedef float evoasm_loss_t;
|
|
25
|
+
|
|
26
|
+
#include "evoasm-program.h"
|
|
27
|
+
#include "evoasm-program-io.h"
|
|
28
|
+
|
|
29
|
+
#define EVOASM_POP_PARAMS_MAX_PARAMS 32
|
|
30
|
+
|
|
31
|
+
typedef enum {
|
|
32
|
+
EVOASM_POP_PARAMS_ERROR_CODE_INVALID
|
|
33
|
+
} evoasm_pop_params_error_code_t;
|
|
34
|
+
|
|
35
|
+
typedef struct evoasm_pop_params_s {
|
|
36
|
+
evoasm_param_id_t param_ids[EVOASM_POP_PARAMS_MAX_PARAMS];
|
|
37
|
+
evoasm_domain_t *domains[EVOASM_POP_PARAMS_MAX_PARAMS];
|
|
38
|
+
uint8_t n_params;
|
|
39
|
+
|
|
40
|
+
uint16_t n_demes;
|
|
41
|
+
uint16_t library_size;
|
|
42
|
+
uint16_t deme_size;
|
|
43
|
+
uint16_t kernel_size;
|
|
44
|
+
uint16_t program_size;
|
|
45
|
+
uint16_t min_module_size;
|
|
46
|
+
uint16_t max_module_size;
|
|
47
|
+
float mut_rate;
|
|
48
|
+
float evap_rate;
|
|
49
|
+
|
|
50
|
+
uint8_t depth;
|
|
51
|
+
evoasm_prng_state_t seed;
|
|
52
|
+
uint32_t recur_limit;
|
|
53
|
+
uint16_t n_insts;
|
|
54
|
+
evoasm_program_io_t *program_input;
|
|
55
|
+
evoasm_program_io_t *program_output;
|
|
56
|
+
evoasm_inst_id_t inst_ids[EVOASM_X64_INST_NONE];
|
|
57
|
+
} evoasm_pop_params_t;
|
|
58
|
+
|
|
59
|
+
bool
|
|
60
|
+
evoasm_pop_params_validate(evoasm_pop_params_t *pop_params);
|
|
@@ -0,0 +1,1323 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2016 Julian Aron Prenner
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
6
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include "evoasm-pop.h"
|
|
19
|
+
#include "evoasm-signal.h"
|
|
20
|
+
#include "evoasm-util.h"
|
|
21
|
+
#include "evoasm-program.h"
|
|
22
|
+
#include "evoasm-error.h"
|
|
23
|
+
|
|
24
|
+
#ifdef _OPENMP
|
|
25
|
+
|
|
26
|
+
# include <omp.h>
|
|
27
|
+
#include <gen/evoasm-x64-params.h>
|
|
28
|
+
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
EVOASM_DEF_LOG_TAG("pop")
|
|
32
|
+
|
|
33
|
+
#define EVOASM_DEME_MIN_LOSS_SAMPLES 8
|
|
34
|
+
#define EVOASM_DEME_MAX_LOSS_SAMPLES 16
|
|
35
|
+
|
|
36
|
+
#define EVOASM_DEME_INDIV_OFF(deme, row, indiv_idx) \
|
|
37
|
+
((size_t)((row) * (size_t)(deme)->params->deme_size + (indiv_idx)))
|
|
38
|
+
|
|
39
|
+
#define EVOASM_DEME_LOSS_SAMPLE_OFF(deme, row, indiv_idx, sample_idx) \
|
|
40
|
+
(EVOASM_DEME_INDIV_OFF(deme, row, indiv_idx) * EVOASM_DEME_MAX_LOSS_SAMPLES + (sample_idx))
|
|
41
|
+
|
|
42
|
+
/* first sample is replaced with median loss after update */
|
|
43
|
+
#define EVOASM_DEME_LOSS_OFF(deme, row, indiv_idx) \
|
|
44
|
+
EVOASM_DEME_LOSS_SAMPLE_OFF(deme, row, indiv_idx, 0)
|
|
45
|
+
|
|
46
|
+
#define EVOASM_DEME_PROGRAMS_ROW(deme) ((deme)->params->program_size)
|
|
47
|
+
|
|
48
|
+
#define EVOASM_DEME_PROGRAM_POS_OFF_(program_size, program_idx, pos) \
|
|
49
|
+
(((program_idx) * (size_t)(program_size) + (pos)))
|
|
50
|
+
|
|
51
|
+
#define EVOASM_DEME_PROGRAM_POS_OFF(deme, program_idx, pos) \
|
|
52
|
+
EVOASM_DEME_PROGRAM_POS_OFF_((deme)->params->program_size, program_idx, pos)
|
|
53
|
+
|
|
54
|
+
#define EVOASM_DEME_KERNEL_INST_OFF_(deme_size, kernel_size, pos, kernel_idx, inst_idx) \
|
|
55
|
+
((((pos) * (deme_size) + (kernel_idx)) * (kernel_size) + (inst_idx)))
|
|
56
|
+
|
|
57
|
+
#define EVOASM_DEME_KERNEL_INST_OFF(deme, pos, kernel_idx, inst_idx) \
|
|
58
|
+
EVOASM_DEME_KERNEL_INST_OFF_((deme)->params->deme_size, (deme)->params->kernel_size, pos, kernel_idx, inst_idx)
|
|
59
|
+
|
|
60
|
+
#define EVOASM_DEME_N_INDIVS(deme) ((evoasm_pop_params_get_deme_height((deme)->params)) * (deme)->params->deme_size)
|
|
61
|
+
|
|
62
|
+
static evoasm_success_t
|
|
63
|
+
evoasm_pop_loss_data_init(evoasm_pop_loss_data_t *loss_data, size_t n_indivs) {
|
|
64
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, loss_data->samples, EVOASM_CACHE_LINE_SIZE,
|
|
65
|
+
n_indivs * EVOASM_DEME_MAX_LOSS_SAMPLES,
|
|
66
|
+
sizeof(evoasm_loss_t));
|
|
67
|
+
|
|
68
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, loss_data->counters, EVOASM_CACHE_LINE_SIZE,
|
|
69
|
+
n_indivs,
|
|
70
|
+
sizeof(uint8_t));
|
|
71
|
+
|
|
72
|
+
return true;
|
|
73
|
+
error:
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static void
|
|
78
|
+
evoasm_pop_loss_data_destroy(evoasm_pop_loss_data_t *loss_data) {
|
|
79
|
+
evoasm_free(loss_data->samples);
|
|
80
|
+
evoasm_free(loss_data->counters);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static evoasm_success_t
|
|
84
|
+
evoasm_pop_program_data_init(evoasm_pop_program_data_t *program_data, size_t n_pos) {
|
|
85
|
+
|
|
86
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, program_data->jmp_offs, EVOASM_CACHE_LINE_SIZE,
|
|
87
|
+
n_pos,
|
|
88
|
+
sizeof(int16_t));
|
|
89
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, program_data->jmp_cond, EVOASM_CACHE_LINE_SIZE,
|
|
90
|
+
n_pos,
|
|
91
|
+
sizeof(uint8_t));
|
|
92
|
+
|
|
93
|
+
return true;
|
|
94
|
+
|
|
95
|
+
error:
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
static void
|
|
100
|
+
evoasm_pop_program_data_destroy(evoasm_pop_program_data_t *program_data) {
|
|
101
|
+
evoasm_free(program_data->jmp_offs);
|
|
102
|
+
evoasm_free(program_data->jmp_cond);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static evoasm_success_t
|
|
106
|
+
evoasm_pop_kernel_data_init(evoasm_pop_kernel_data_t *kernel_data,
|
|
107
|
+
evoasm_arch_id_t arch_id,
|
|
108
|
+
size_t n_insts) {
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, kernel_data->insts, EVOASM_CACHE_LINE_SIZE,
|
|
112
|
+
n_insts,
|
|
113
|
+
sizeof(evoasm_inst_id_t));
|
|
114
|
+
|
|
115
|
+
switch(arch_id) {
|
|
116
|
+
case EVOASM_ARCH_X64:
|
|
117
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, kernel_data->params.x64, EVOASM_CACHE_LINE_SIZE,
|
|
118
|
+
n_insts,
|
|
119
|
+
sizeof(evoasm_x64_basic_params_t));
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
evoasm_assert_not_reached();
|
|
123
|
+
}
|
|
124
|
+
return true;
|
|
125
|
+
|
|
126
|
+
error:
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
static void
|
|
131
|
+
evoasm_pop_kernel_data_destroy(evoasm_pop_kernel_data_t *kernel_data) {
|
|
132
|
+
evoasm_free(kernel_data->insts);
|
|
133
|
+
evoasm_free(kernel_data->params.data);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static evoasm_success_t
|
|
137
|
+
evoasm_pop_module_data_init(evoasm_pop_module_data_t *module_data, size_t n) {
|
|
138
|
+
EVOASM_TRY(error, evoasm_pop_program_data_init, &module_data->program_data, n);
|
|
139
|
+
|
|
140
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, module_data->sizes, EVOASM_CACHE_LINE_SIZE,
|
|
141
|
+
n,
|
|
142
|
+
sizeof(uint16_t));
|
|
143
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, module_data->pheromones, EVOASM_CACHE_LINE_SIZE,
|
|
144
|
+
n,
|
|
145
|
+
sizeof(float));
|
|
146
|
+
return true;
|
|
147
|
+
error:
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static void
|
|
152
|
+
evoasm_pop_module_data_destroy(evoasm_pop_module_data_t *module_data) {
|
|
153
|
+
evoasm_pop_program_data_destroy(&module_data->program_data);
|
|
154
|
+
evoasm_free(module_data->pheromones);
|
|
155
|
+
evoasm_free(module_data->sizes);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static inline size_t
|
|
159
|
+
evoasm_pop_params_get_deme_height_(evoasm_pop_params_t *params) {
|
|
160
|
+
size_t height = params->program_size;
|
|
161
|
+
if(params->program_size > 1) return height + 1;
|
|
162
|
+
return height;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
size_t
|
|
166
|
+
evoasm_pop_params_get_deme_height(evoasm_pop_params_t *params) {
|
|
167
|
+
return evoasm_pop_params_get_deme_height_(params);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
static void
|
|
171
|
+
evoasm_deme_destroy(evoasm_deme_t *deme) {
|
|
172
|
+
EVOASM_TRY_WARN(evoasm_program_destroy, &deme->program);
|
|
173
|
+
evoasm_prng_destroy(&deme->prng);
|
|
174
|
+
evoasm_free(deme->blessed_indiv_idxs);
|
|
175
|
+
evoasm_free(deme->doomed_indiv_idxs);
|
|
176
|
+
evoasm_free(deme->error_counters);
|
|
177
|
+
evoasm_free(deme->top_losses);
|
|
178
|
+
|
|
179
|
+
evoasm_pop_kernel_data_destroy(&deme->kernel_data);
|
|
180
|
+
evoasm_pop_loss_data_destroy(&deme->loss_data);
|
|
181
|
+
|
|
182
|
+
evoasm_pop_kernel_data_destroy(&deme->best_kernel_data);
|
|
183
|
+
|
|
184
|
+
if(deme->params->program_size > 1) {
|
|
185
|
+
evoasm_pop_program_data_destroy(&deme->best_program_data);
|
|
186
|
+
evoasm_pop_program_data_destroy(&deme->parent_program_data);
|
|
187
|
+
evoasm_pop_program_data_destroy(&deme->program_data);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
evoasm_pop_kernel_data_destroy(&deme->parent_kernel_data);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
void
|
|
194
|
+
evoasm_pop_destroy(evoasm_pop_t *pop) {
|
|
195
|
+
evoasm_free(pop->domains);
|
|
196
|
+
|
|
197
|
+
for(int i = 0; i < pop->params->n_demes; i++) {
|
|
198
|
+
evoasm_deme_destroy(&pop->demes[i]);
|
|
199
|
+
}
|
|
200
|
+
evoasm_free(pop->demes);
|
|
201
|
+
evoasm_free(pop->summary_losses);
|
|
202
|
+
|
|
203
|
+
evoasm_pop_module_data_destroy(&pop->module_data);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
static evoasm_success_t
|
|
207
|
+
evoasm_deme_init(evoasm_deme_t *deme,
|
|
208
|
+
evoasm_arch_id_t arch_id,
|
|
209
|
+
evoasm_pop_params_t *params,
|
|
210
|
+
evoasm_prng_state_t *seed,
|
|
211
|
+
evoasm_domain_t *domains) {
|
|
212
|
+
|
|
213
|
+
size_t n_examples = EVOASM_PROGRAM_INPUT_N_TUPLES(params->program_input);
|
|
214
|
+
static evoasm_deme_t zero_deme = {0};
|
|
215
|
+
|
|
216
|
+
*deme = zero_deme;
|
|
217
|
+
deme->n_examples = (uint16_t) n_examples;
|
|
218
|
+
deme->arch_id = arch_id;
|
|
219
|
+
deme->params = params;
|
|
220
|
+
deme->domains = domains;
|
|
221
|
+
|
|
222
|
+
evoasm_prng_init(&deme->prng, seed);
|
|
223
|
+
|
|
224
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, deme->blessed_indiv_idxs, EVOASM_CACHE_LINE_SIZE, params->deme_size,
|
|
225
|
+
sizeof(uint16_t));
|
|
226
|
+
|
|
227
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, deme->doomed_indiv_idxs, EVOASM_CACHE_LINE_SIZE, params->deme_size,
|
|
228
|
+
sizeof(uint16_t));
|
|
229
|
+
|
|
230
|
+
EVOASM_TRY(error, evoasm_program_init, &deme->program,
|
|
231
|
+
evoasm_get_arch_info(arch_id),
|
|
232
|
+
params->program_size,
|
|
233
|
+
params->kernel_size,
|
|
234
|
+
n_examples,
|
|
235
|
+
params->recur_limit,
|
|
236
|
+
true);
|
|
237
|
+
|
|
238
|
+
if(params->program_size > 1) {
|
|
239
|
+
EVOASM_TRY(error, evoasm_pop_program_data_init, &deme->program_data,
|
|
240
|
+
(size_t) params->deme_size * params->kernel_size);
|
|
241
|
+
|
|
242
|
+
EVOASM_TRY(error, evoasm_pop_program_data_init, &deme->parent_program_data,
|
|
243
|
+
2u * params->program_size);
|
|
244
|
+
|
|
245
|
+
EVOASM_TRY(error, evoasm_pop_program_data_init, &deme->best_program_data, params->program_size);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
EVOASM_TRY(error, evoasm_pop_kernel_data_init, &deme->parent_kernel_data, arch_id,
|
|
249
|
+
2u * params->kernel_size);
|
|
250
|
+
|
|
251
|
+
size_t n_indivs = EVOASM_DEME_N_INDIVS(deme);
|
|
252
|
+
size_t height = evoasm_pop_params_get_deme_height_(deme->params);
|
|
253
|
+
|
|
254
|
+
EVOASM_TRY(error, evoasm_pop_kernel_data_init, &deme->kernel_data, arch_id,
|
|
255
|
+
(size_t) params->program_size * params->deme_size * params->kernel_size);
|
|
256
|
+
EVOASM_TRY(error, evoasm_pop_loss_data_init, &deme->loss_data, n_indivs);
|
|
257
|
+
|
|
258
|
+
EVOASM_TRY(error, evoasm_pop_kernel_data_init, &deme->best_kernel_data, arch_id,
|
|
259
|
+
(size_t) (params->program_size * params->kernel_size));
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
deme->best_loss = INFINITY;
|
|
263
|
+
|
|
264
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, deme->top_losses, EVOASM_CACHE_LINE_SIZE,
|
|
265
|
+
height,
|
|
266
|
+
sizeof(evoasm_loss_t));
|
|
267
|
+
|
|
268
|
+
for(size_t i = 0; i < height; i++) {
|
|
269
|
+
deme->top_losses[i] = INFINITY;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, deme->error_counters, (size_t) n_examples, EVOASM_CACHE_LINE_SIZE,
|
|
273
|
+
sizeof(uint64_t));
|
|
274
|
+
deme->error_counter = 0;
|
|
275
|
+
|
|
276
|
+
return true;
|
|
277
|
+
|
|
278
|
+
error:
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
evoasm_success_t
|
|
283
|
+
evoasm_pop_init_domains(evoasm_pop_t *pop) {
|
|
284
|
+
size_t i, j, k;
|
|
285
|
+
evoasm_domain_t cloned_domain;
|
|
286
|
+
|
|
287
|
+
evoasm_pop_params_t *params = pop->params;
|
|
288
|
+
|
|
289
|
+
size_t domains_len = (size_t) (params->n_insts * params->n_params);
|
|
290
|
+
pop->domains = evoasm_calloc(domains_len,
|
|
291
|
+
sizeof(evoasm_domain_t));
|
|
292
|
+
|
|
293
|
+
if(!pop->domains) goto fail;
|
|
294
|
+
|
|
295
|
+
for(i = 0; i < params->n_insts; i++) {
|
|
296
|
+
evoasm_x64_inst_t *inst = evoasm_x64_inst_((evoasm_x64_inst_id_t) params->inst_ids[i]);
|
|
297
|
+
for(j = 0; j < params->n_params; j++) {
|
|
298
|
+
evoasm_domain_t *inst_domain = &pop->domains[i * params->n_params + j];
|
|
299
|
+
evoasm_param_id_t param_id = params->param_ids[j];
|
|
300
|
+
for(k = 0; k < inst->n_params; k++) {
|
|
301
|
+
evoasm_param_t *param = &inst->params[k];
|
|
302
|
+
if(param->id == param_id) {
|
|
303
|
+
evoasm_domain_t *user_domain = params->domains[param_id];
|
|
304
|
+
if(user_domain != NULL) {
|
|
305
|
+
if(evoasm_domain_is_empty(user_domain)) goto empty_domain;
|
|
306
|
+
|
|
307
|
+
evoasm_domain_clone(user_domain, &cloned_domain);
|
|
308
|
+
evoasm_domain_intersect(&cloned_domain, param->domain, inst_domain);
|
|
309
|
+
if(evoasm_domain_is_empty(inst_domain)) goto empty_domain;
|
|
310
|
+
} else {
|
|
311
|
+
evoasm_domain_clone(param->domain, inst_domain);
|
|
312
|
+
}
|
|
313
|
+
goto found;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/* not found */
|
|
317
|
+
inst_domain->type = EVOASM_DOMAIN_TYPE_NONE;
|
|
318
|
+
found:;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/*
|
|
323
|
+
for(i = 0; i < domains_len; i++) {
|
|
324
|
+
evoasm_domain_log(&pop->domains[i], EVOASM_LOG_LEVEL_WARN);
|
|
325
|
+
}*/
|
|
326
|
+
|
|
327
|
+
return true;
|
|
328
|
+
|
|
329
|
+
fail:
|
|
330
|
+
return false;
|
|
331
|
+
|
|
332
|
+
empty_domain:
|
|
333
|
+
evoasm_error(EVOASM_ERROR_TYPE_POP, EVOASM_ERROR_CODE_NONE,
|
|
334
|
+
"Empty domain");
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
evoasm_success_t
|
|
339
|
+
evoasm_pop_init(evoasm_pop_t *pop,
|
|
340
|
+
evoasm_arch_id_t arch_id,
|
|
341
|
+
evoasm_pop_params_t *params) {
|
|
342
|
+
static evoasm_pop_t zero_pop = {0};
|
|
343
|
+
evoasm_prng_t seed_prng;
|
|
344
|
+
|
|
345
|
+
*pop = zero_pop;
|
|
346
|
+
|
|
347
|
+
pop->params = params;
|
|
348
|
+
|
|
349
|
+
if(!evoasm_pop_params_validate(params)) goto error;
|
|
350
|
+
|
|
351
|
+
#ifdef _OPENMP
|
|
352
|
+
{
|
|
353
|
+
int max_threads;
|
|
354
|
+
max_threads = omp_get_max_threads();
|
|
355
|
+
omp_set_dynamic(0);
|
|
356
|
+
int n_threads = EVOASM_MIN(max_threads, params->n_demes);
|
|
357
|
+
omp_set_num_threads(n_threads);
|
|
358
|
+
evoasm_log_info("Using OpenMP with %d threads", n_threads);
|
|
359
|
+
}
|
|
360
|
+
#endif
|
|
361
|
+
|
|
362
|
+
evoasm_prng_init(&seed_prng, ¶ms->seed);
|
|
363
|
+
|
|
364
|
+
EVOASM_TRY(error, evoasm_pop_init_domains, pop);
|
|
365
|
+
EVOASM_TRY(error, evoasm_pop_module_data_init, &pop->module_data, params->library_size);
|
|
366
|
+
|
|
367
|
+
EVOASM_TRY_ALLOC(error, aligned_calloc, pop->demes, EVOASM_CACHE_LINE_SIZE, (size_t) params->n_demes,
|
|
368
|
+
sizeof(evoasm_deme_t));
|
|
369
|
+
|
|
370
|
+
for(int i = 0; i < params->n_demes; i++) {
|
|
371
|
+
evoasm_prng_state_t seed;
|
|
372
|
+
|
|
373
|
+
for(int j = 0; j < EVOASM_PRNG_SEED_LEN; j++) {
|
|
374
|
+
seed.data[j] = evoasm_prng_rand64_(&seed_prng);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
EVOASM_TRY(error, evoasm_deme_init,
|
|
378
|
+
&pop->demes[i],
|
|
379
|
+
arch_id,
|
|
380
|
+
params,
|
|
381
|
+
&seed,
|
|
382
|
+
pop->domains);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return true;
|
|
386
|
+
|
|
387
|
+
error:
|
|
388
|
+
evoasm_pop_destroy(pop);
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
static void
|
|
393
|
+
evoasm_deme_seed_kernel_param_x64(evoasm_deme_t *deme, evoasm_inst_id_t *inst_id_ptr,
|
|
394
|
+
evoasm_x64_basic_params_t *params_ptr) {
|
|
395
|
+
evoasm_pop_params_t *params = deme->params;
|
|
396
|
+
size_t n_params = params->n_params;
|
|
397
|
+
evoasm_prng_t *prng = &deme->prng;
|
|
398
|
+
|
|
399
|
+
size_t inst_idx = (size_t) evoasm_prng_rand_between_(prng, 0, params->n_insts - 1);
|
|
400
|
+
evoasm_inst_id_t inst_id = params->inst_ids[inst_idx];
|
|
401
|
+
|
|
402
|
+
*inst_id_ptr = inst_id;
|
|
403
|
+
|
|
404
|
+
/* set parameters */
|
|
405
|
+
for(size_t i = 0; i < n_params; i++) {
|
|
406
|
+
evoasm_domain_t *domain = &deme->domains[inst_idx * n_params + i];
|
|
407
|
+
if(domain->type < EVOASM_DOMAIN_TYPE_NONE) {
|
|
408
|
+
evoasm_x64_param_id_t param_id = (evoasm_x64_param_id_t) deme->params->param_ids[i];
|
|
409
|
+
evoasm_param_val_t param_val;
|
|
410
|
+
|
|
411
|
+
param_val = (int64_t) evoasm_domain_rand_(domain, prng);
|
|
412
|
+
evoasm_x64_basic_params_set_(params_ptr, param_id, param_val);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
static void
|
|
418
|
+
evoasm_deme_seed_kernel_inst(evoasm_deme_t *deme,
|
|
419
|
+
size_t pos,
|
|
420
|
+
size_t kernel_idx,
|
|
421
|
+
size_t inst_idx) {
|
|
422
|
+
|
|
423
|
+
size_t kernel_inst_off = EVOASM_DEME_KERNEL_INST_OFF(deme, pos, kernel_idx, inst_idx);
|
|
424
|
+
|
|
425
|
+
evoasm_pop_kernel_data_t *kernel_data = &deme->kernel_data;
|
|
426
|
+
evoasm_inst_id_t *insts_ptr = &kernel_data->insts[kernel_inst_off];
|
|
427
|
+
|
|
428
|
+
switch(deme->arch_id) {
|
|
429
|
+
case EVOASM_ARCH_X64: {
|
|
430
|
+
evoasm_x64_basic_params_t *params_ptr = &kernel_data->params.x64[kernel_inst_off];
|
|
431
|
+
evoasm_deme_seed_kernel_param_x64(deme, insts_ptr, params_ptr);
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
default:
|
|
435
|
+
evoasm_assert_not_reached();
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
static void
|
|
440
|
+
evoasm_deme_seed_kernel(evoasm_deme_t *deme, size_t pos, size_t kernel_idx) {
|
|
441
|
+
for(size_t i = 0; i < deme->params->kernel_size; i++) {
|
|
442
|
+
evoasm_deme_seed_kernel_inst(deme, pos, kernel_idx, i);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
static void
|
|
447
|
+
evoasm_deme_seed_program_pos(evoasm_deme_t *deme,
|
|
448
|
+
size_t program_idx,
|
|
449
|
+
size_t pos) {
|
|
450
|
+
|
|
451
|
+
size_t program_pos_off = EVOASM_DEME_PROGRAM_POS_OFF(deme, program_idx, pos);
|
|
452
|
+
evoasm_pop_program_data_t *program_data = &deme->program_data;
|
|
453
|
+
evoasm_prng_t *prng = &deme->prng;
|
|
454
|
+
size_t program_size = deme->params->program_size;
|
|
455
|
+
|
|
456
|
+
program_data->jmp_cond[program_pos_off] =
|
|
457
|
+
(uint8_t) evoasm_prng_rand8_(prng);
|
|
458
|
+
|
|
459
|
+
program_data->jmp_offs[program_pos_off] =
|
|
460
|
+
(int16_t) (evoasm_prng_rand_between_(prng, 0, (int64_t) (program_size - 1)) - (int64_t) (program_size / 2));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
static void
|
|
464
|
+
evoasm_deme_seed_program(evoasm_deme_t *deme,
|
|
465
|
+
size_t program_idx) {
|
|
466
|
+
for(size_t i = 0; i < deme->params->program_size; i++) {
|
|
467
|
+
evoasm_deme_seed_program_pos(deme, program_idx, i);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
static void
|
|
472
|
+
evoasm_deme_seed(evoasm_deme_t *deme) {
|
|
473
|
+
if(deme->params->program_size > 1) {
|
|
474
|
+
for(size_t i = 0; i < deme->params->deme_size; i++) {
|
|
475
|
+
evoasm_deme_seed_program(deme, i);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
for(size_t i = 0; i < deme->params->program_size; i++) {
|
|
480
|
+
for(size_t j = 0; j < deme->params->deme_size; j++) {
|
|
481
|
+
evoasm_deme_seed_kernel(deme, i, j);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
evoasm_success_t
|
|
487
|
+
evoasm_pop_seed(evoasm_pop_t *pop) {
|
|
488
|
+
|
|
489
|
+
#pragma omp parallel for
|
|
490
|
+
for(size_t i = 0; i < pop->params->n_demes; i++) {
|
|
491
|
+
evoasm_deme_seed(&pop->demes[i]);
|
|
492
|
+
}
|
|
493
|
+
pop->seeded = true;
|
|
494
|
+
return true;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
static void
|
|
498
|
+
evoasm_deme_load_program_(evoasm_deme_t *deme,
|
|
499
|
+
evoasm_program_t *program,
|
|
500
|
+
evoasm_pop_program_data_t *program_data,
|
|
501
|
+
evoasm_pop_kernel_data_t *kernel_data,
|
|
502
|
+
size_t program_idx,
|
|
503
|
+
size_t *kernel_idxs,
|
|
504
|
+
size_t deme_size) {
|
|
505
|
+
|
|
506
|
+
size_t program_size = deme->params->program_size;
|
|
507
|
+
size_t kernel_size = deme->params->kernel_size;
|
|
508
|
+
|
|
509
|
+
for(size_t i = 0; i < program_size; i++) {
|
|
510
|
+
size_t kernel_idx = kernel_idxs[i];
|
|
511
|
+
size_t inst0_off = EVOASM_DEME_KERNEL_INST_OFF_(deme_size, kernel_size, i, kernel_idx, 0);
|
|
512
|
+
evoasm_kernel_t *kernel = &program->kernels[i];
|
|
513
|
+
|
|
514
|
+
if(program->shallow) {
|
|
515
|
+
kernel->insts = &kernel_data->insts[inst0_off];
|
|
516
|
+
} else {
|
|
517
|
+
EVOASM_MEMCPY_N(kernel->insts,
|
|
518
|
+
&kernel_data->insts[inst0_off], kernel->size);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
switch(deme->arch_id) {
|
|
522
|
+
case EVOASM_ARCH_X64:
|
|
523
|
+
if(program->shallow) {
|
|
524
|
+
kernel->params.x64 = &kernel_data->params.x64[inst0_off];
|
|
525
|
+
} else {
|
|
526
|
+
EVOASM_MEMCPY_N(kernel->params.x64,
|
|
527
|
+
&kernel_data->params.x64[inst0_off], kernel->size);
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
default:
|
|
531
|
+
evoasm_assert_not_reached();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if(program_size > 1) {
|
|
536
|
+
for(size_t i = 0; i < program_size; i++) {
|
|
537
|
+
size_t program_pos_off = EVOASM_DEME_PROGRAM_POS_OFF_(program_size, program_idx, i);
|
|
538
|
+
program->jmp_offs[i] = program_data->jmp_offs[program_pos_off];
|
|
539
|
+
program->jmp_conds[i] = program_data->jmp_cond[program_pos_off];
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
static inline void
|
|
545
|
+
evoasm_deme_load_program(evoasm_deme_t *deme,
|
|
546
|
+
evoasm_program_t *program,
|
|
547
|
+
evoasm_pop_program_data_t *program_data,
|
|
548
|
+
evoasm_pop_kernel_data_t *kernel_data,
|
|
549
|
+
size_t program_idx,
|
|
550
|
+
size_t *kernel_idxs) {
|
|
551
|
+
|
|
552
|
+
evoasm_deme_load_program_(deme, program, program_data,
|
|
553
|
+
kernel_data, program_idx, kernel_idxs,
|
|
554
|
+
deme->params->deme_size);
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
static evoasm_success_t
|
|
559
|
+
evoasm_deme_eval_program(evoasm_deme_t *deme, evoasm_program_t *program, evoasm_loss_t *ret_loss) {
|
|
560
|
+
evoasm_pop_params_t *params = deme->params;
|
|
561
|
+
|
|
562
|
+
//bool prepare, bool emit_kernels, bool emit_io_load_store, bool set_io_mapping
|
|
563
|
+
evoasm_program_emit_flags_t emit_flags =
|
|
564
|
+
EVOASM_PROGRAM_EMIT_FLAG_PREPARE |
|
|
565
|
+
EVOASM_PROGRAM_EMIT_FLAG_EMIT_KERNELS |
|
|
566
|
+
EVOASM_PROGRAM_EMIT_FLAG_EMIT_IO_LOAD_STORE |
|
|
567
|
+
EVOASM_PROGRAM_EMIT_FLAG_SET_IO_MAPPING;
|
|
568
|
+
|
|
569
|
+
if(!evoasm_program_emit(program, params->program_input, emit_flags)) {
|
|
570
|
+
*ret_loss = INFINITY;
|
|
571
|
+
|
|
572
|
+
if(evoasm_last_error.code == EVOASM_PROGRAM_ERROR_CODE_NO_OUTPUT) {
|
|
573
|
+
/* do not abort on this error, instead just let loss be infinity */
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
*ret_loss = evoasm_program_eval(program, params->program_output);
|
|
580
|
+
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
static void
|
|
585
|
+
evoasm_deme_register_loss_sample(evoasm_deme_t *deme, size_t row, size_t indiv_idx, evoasm_loss_t loss) {
|
|
586
|
+
size_t indiv_off = EVOASM_DEME_INDIV_OFF(deme, row, indiv_idx);
|
|
587
|
+
size_t sample_counter = deme->loss_data.counters[indiv_off];
|
|
588
|
+
|
|
589
|
+
if(sample_counter < EVOASM_DEME_MAX_LOSS_SAMPLES) {
|
|
590
|
+
size_t sample_off = EVOASM_DEME_LOSS_SAMPLE_OFF(deme, row, indiv_idx, sample_counter);
|
|
591
|
+
deme->loss_data.samples[sample_off] = loss;
|
|
592
|
+
deme->loss_data.counters[indiv_off]++;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
static evoasm_deme_t *
|
|
598
|
+
evoasm_pop_find_best_deme(evoasm_pop_t *pop) {
|
|
599
|
+
evoasm_deme_t *best_deme = &pop->demes[0];
|
|
600
|
+
evoasm_loss_t best_loss = best_deme->best_loss;
|
|
601
|
+
|
|
602
|
+
for(size_t i = 1; i < pop->params->n_demes; i++) {
|
|
603
|
+
evoasm_deme_t *deme = &pop->demes[i];
|
|
604
|
+
if(deme->best_loss < best_loss) {
|
|
605
|
+
best_loss = deme->best_loss;
|
|
606
|
+
best_deme = deme;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return best_deme;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
evoasm_success_t
|
|
613
|
+
evoasm_pop_load_best_program(evoasm_pop_t *pop, evoasm_program_t *program) {
|
|
614
|
+
|
|
615
|
+
evoasm_deme_t *best_deme = evoasm_pop_find_best_deme(pop);
|
|
616
|
+
evoasm_pop_params_t *params = best_deme->params;
|
|
617
|
+
|
|
618
|
+
EVOASM_TRY(error, evoasm_program_init, program,
|
|
619
|
+
evoasm_get_arch_info(best_deme->arch_id),
|
|
620
|
+
params->program_size,
|
|
621
|
+
params->kernel_size,
|
|
622
|
+
best_deme->n_examples,
|
|
623
|
+
params->recur_limit,
|
|
624
|
+
false);
|
|
625
|
+
|
|
626
|
+
size_t program_idx = 0;
|
|
627
|
+
size_t kernel_idxs[EVOASM_PROGRAM_MAX_SIZE] = {0};
|
|
628
|
+
|
|
629
|
+
evoasm_deme_load_program_(best_deme,
|
|
630
|
+
program,
|
|
631
|
+
&best_deme->best_program_data,
|
|
632
|
+
&best_deme->best_kernel_data,
|
|
633
|
+
program_idx,
|
|
634
|
+
kernel_idxs,
|
|
635
|
+
1);
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
program->_input = *params->program_input;
|
|
639
|
+
program->_output = *params->program_output;
|
|
640
|
+
program->_input.len = 0;
|
|
641
|
+
program->_output.len = 0;
|
|
642
|
+
|
|
643
|
+
evoasm_program_emit_flags_t emit_flags =
|
|
644
|
+
EVOASM_PROGRAM_EMIT_FLAG_PREPARE |
|
|
645
|
+
EVOASM_PROGRAM_EMIT_FLAG_EMIT_KERNELS |
|
|
646
|
+
EVOASM_PROGRAM_EMIT_FLAG_EMIT_IO_LOAD_STORE |
|
|
647
|
+
EVOASM_PROGRAM_EMIT_FLAG_SET_IO_MAPPING;
|
|
648
|
+
|
|
649
|
+
EVOASM_TRY(error, evoasm_program_emit, program, params->program_input, emit_flags);
|
|
650
|
+
|
|
651
|
+
evoasm_signal_set_exception_mask(program->exception_mask);
|
|
652
|
+
evoasm_loss_t loss = evoasm_program_eval(program, params->program_output);
|
|
653
|
+
assert(loss == best_deme->best_loss);
|
|
654
|
+
evoasm_signal_clear_exception_mask();
|
|
655
|
+
|
|
656
|
+
return true;
|
|
657
|
+
|
|
658
|
+
error:
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
static evoasm_success_t
|
|
663
|
+
evoasm_deme_test_program(evoasm_deme_t *deme, size_t program_idx, size_t *kernel_idxs, evoasm_loss_t *ret_loss) {
|
|
664
|
+
|
|
665
|
+
evoasm_loss_t loss;
|
|
666
|
+
evoasm_program_t *program = &deme->program;
|
|
667
|
+
evoasm_pop_kernel_data_t *kernel_data = &deme->kernel_data;
|
|
668
|
+
evoasm_pop_program_data_t *program_data = &deme->program_data;
|
|
669
|
+
|
|
670
|
+
evoasm_deme_load_program(deme, program, program_data, kernel_data, program_idx, kernel_idxs);
|
|
671
|
+
|
|
672
|
+
EVOASM_TRY(error, evoasm_deme_eval_program, deme, program, &loss);
|
|
673
|
+
|
|
674
|
+
size_t program_size = deme->params->program_size;
|
|
675
|
+
|
|
676
|
+
for(size_t i = 0; i < program_size; i++) {
|
|
677
|
+
evoasm_deme_register_loss_sample(deme, i, kernel_idxs[i], loss);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if(program_size > 1) {
|
|
681
|
+
evoasm_deme_register_loss_sample(deme, EVOASM_DEME_PROGRAMS_ROW(deme),
|
|
682
|
+
program_idx, loss);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
*ret_loss = loss;
|
|
686
|
+
return true;
|
|
687
|
+
error:
|
|
688
|
+
return false;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
static void
|
|
693
|
+
evoasm_pop_program_data_copy(evoasm_pop_program_data_t *program_data,
|
|
694
|
+
size_t off,
|
|
695
|
+
evoasm_pop_program_data_t *dst,
|
|
696
|
+
size_t dst_off,
|
|
697
|
+
size_t len) {
|
|
698
|
+
|
|
699
|
+
memcpy(dst->jmp_offs + dst_off, program_data->jmp_offs + off,
|
|
700
|
+
sizeof(int16_t) * len);
|
|
701
|
+
memcpy(dst->jmp_cond + dst_off, program_data->jmp_cond + off,
|
|
702
|
+
sizeof(uint8_t) * len);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
static evoasm_used void
|
|
706
|
+
evoasm_pop_program_data_move(evoasm_pop_program_data_t *program_data,
|
|
707
|
+
size_t src_off,
|
|
708
|
+
size_t dst_off,
|
|
709
|
+
size_t len) {
|
|
710
|
+
|
|
711
|
+
memmove(program_data->jmp_offs + dst_off, program_data->jmp_offs + src_off,
|
|
712
|
+
sizeof(int16_t) * len);
|
|
713
|
+
memmove(program_data->jmp_cond + dst_off, program_data->jmp_cond + src_off,
|
|
714
|
+
sizeof(uint8_t) * len);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
static void
|
|
719
|
+
evoasm_pop_kernel_data_copy(evoasm_pop_kernel_data_t *kernel_data,
|
|
720
|
+
evoasm_arch_id_t arch_id,
|
|
721
|
+
size_t off,
|
|
722
|
+
evoasm_pop_kernel_data_t *dst,
|
|
723
|
+
size_t dst_off,
|
|
724
|
+
size_t len) {
|
|
725
|
+
|
|
726
|
+
memcpy(dst->insts + dst_off, kernel_data->insts + off,
|
|
727
|
+
sizeof(evoasm_inst_id_t) * len);
|
|
728
|
+
|
|
729
|
+
switch(arch_id) {
|
|
730
|
+
case EVOASM_ARCH_X64:
|
|
731
|
+
memcpy(dst->params.x64 + dst_off, kernel_data->params.x64 + off,
|
|
732
|
+
sizeof(evoasm_x64_basic_params_t) * len);
|
|
733
|
+
break;
|
|
734
|
+
default:
|
|
735
|
+
evoasm_assert_not_reached();
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
static evoasm_used void
|
|
740
|
+
evoasm_pop_kernel_data_move(evoasm_pop_kernel_data_t *kernel_data,
|
|
741
|
+
evoasm_arch_id_t arch_id,
|
|
742
|
+
size_t src_off,
|
|
743
|
+
size_t dst_off,
|
|
744
|
+
size_t len) {
|
|
745
|
+
|
|
746
|
+
memmove(kernel_data->insts + dst_off, kernel_data->insts + src_off,
|
|
747
|
+
sizeof(evoasm_inst_id_t) * len);
|
|
748
|
+
|
|
749
|
+
switch(arch_id) {
|
|
750
|
+
case EVOASM_ARCH_X64:
|
|
751
|
+
memmove(kernel_data->params.x64 + dst_off, kernel_data->params.x64 + src_off,
|
|
752
|
+
sizeof(evoasm_x64_basic_params_t) * len);
|
|
753
|
+
break;
|
|
754
|
+
default:
|
|
755
|
+
evoasm_assert_not_reached();
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
static inline void
|
|
760
|
+
evoasm_deme_update_best(evoasm_deme_t *deme, evoasm_loss_t loss, size_t program_idx, size_t *kernel_idxs) {
|
|
761
|
+
|
|
762
|
+
if(loss < deme->best_loss) {
|
|
763
|
+
size_t src_program_pos0_off = EVOASM_DEME_PROGRAM_POS_OFF(deme, program_idx, 0);
|
|
764
|
+
size_t dst_program_pos0_off = EVOASM_DEME_PROGRAM_POS_OFF_(deme->params->program_size, 0, 0);
|
|
765
|
+
|
|
766
|
+
size_t program_size = deme->params->program_size;
|
|
767
|
+
size_t kernel_size = deme->params->kernel_size;
|
|
768
|
+
|
|
769
|
+
evoasm_log_info("new best program loss: %g", loss);
|
|
770
|
+
evoasm_program_log(&deme->program, EVOASM_LOG_LEVEL_INFO);
|
|
771
|
+
|
|
772
|
+
deme->best_loss = loss;
|
|
773
|
+
|
|
774
|
+
if(program_size > 1) {
|
|
775
|
+
evoasm_pop_program_data_copy(&deme->program_data, src_program_pos0_off,
|
|
776
|
+
&deme->best_program_data, dst_program_pos0_off, program_size);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
for(size_t k = 0; k < program_size; k++) {
|
|
780
|
+
size_t src_kernel_inst0_off = EVOASM_DEME_KERNEL_INST_OFF(deme, k, kernel_idxs[k], 0);
|
|
781
|
+
size_t dst_kernel_inst0_off = EVOASM_DEME_KERNEL_INST_OFF_(1, deme->params->kernel_size, k, 0, 0);
|
|
782
|
+
|
|
783
|
+
evoasm_pop_kernel_data_copy(&deme->kernel_data, deme->arch_id, src_kernel_inst0_off,
|
|
784
|
+
&deme->best_kernel_data, dst_kernel_inst0_off, kernel_size);
|
|
785
|
+
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
static evoasm_success_t
|
|
791
|
+
evoasm_deme_test_programs(evoasm_deme_t *deme) {
|
|
792
|
+
evoasm_prng_t *prng = &deme->prng;
|
|
793
|
+
size_t program_size = deme->params->program_size;
|
|
794
|
+
|
|
795
|
+
for(size_t i = 0; i < deme->params->deme_size; i++) {
|
|
796
|
+
for(size_t j = 0; j < EVOASM_DEME_MIN_LOSS_SAMPLES; j++) {
|
|
797
|
+
size_t kernel_idxs[EVOASM_PROGRAM_MAX_SIZE];
|
|
798
|
+
evoasm_loss_t loss;
|
|
799
|
+
|
|
800
|
+
for(size_t k = 0; k < program_size; k++) {
|
|
801
|
+
size_t kernel_idx = (size_t) evoasm_prng_rand_between_(prng, 0,
|
|
802
|
+
deme->params->deme_size - 1);
|
|
803
|
+
kernel_idxs[k] = kernel_idx;
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
EVOASM_TRY(error, evoasm_deme_test_program, deme, i, kernel_idxs, &loss);
|
|
807
|
+
evoasm_deme_update_best(deme, loss, i, kernel_idxs);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
assert(deme->loss_data.counters[EVOASM_DEME_INDIV_OFF(deme, EVOASM_DEME_PROGRAMS_ROW(deme), i)] ==
|
|
811
|
+
EVOASM_DEME_MIN_LOSS_SAMPLES);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
return true;
|
|
815
|
+
|
|
816
|
+
error:
|
|
817
|
+
return false;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
#include <stdlib.h>
|
|
821
|
+
|
|
822
|
+
static evoasm_success_t
|
|
823
|
+
evoasm_deme_test_kernels(evoasm_deme_t *deme) {
|
|
824
|
+
|
|
825
|
+
evoasm_prng_t *prng = &deme->prng;
|
|
826
|
+
size_t kernel_idxs[EVOASM_PROGRAM_MAX_SIZE];
|
|
827
|
+
size_t program_size = deme->params->program_size;
|
|
828
|
+
|
|
829
|
+
for(size_t i = 0; i < deme->params->program_size; i++) {
|
|
830
|
+
for(size_t j = 0; j < deme->params->deme_size; j++) {
|
|
831
|
+
size_t kernel_off = EVOASM_DEME_INDIV_OFF(deme, i, j);
|
|
832
|
+
size_t n_samples = deme->loss_data.counters[kernel_off];
|
|
833
|
+
|
|
834
|
+
for(size_t k = n_samples; k < EVOASM_DEME_MIN_LOSS_SAMPLES; k++) {
|
|
835
|
+
size_t program_idx;
|
|
836
|
+
evoasm_loss_t loss;
|
|
837
|
+
|
|
838
|
+
program_idx = (size_t) evoasm_prng_rand_between_(prng, 0, deme->params->deme_size - 1);
|
|
839
|
+
|
|
840
|
+
for(size_t l = 0; l < program_size; l++) {
|
|
841
|
+
size_t load_kernel_idx;
|
|
842
|
+
|
|
843
|
+
if(l == i) {
|
|
844
|
+
/* the current kernel */
|
|
845
|
+
load_kernel_idx = j;
|
|
846
|
+
} else {
|
|
847
|
+
/* some random other kernel */
|
|
848
|
+
load_kernel_idx = (size_t) evoasm_prng_rand_between_(prng, 0, deme->params->deme_size - 1);
|
|
849
|
+
}
|
|
850
|
+
kernel_idxs[l] = load_kernel_idx;
|
|
851
|
+
}
|
|
852
|
+
EVOASM_TRY(error, evoasm_deme_test_program, deme, program_idx, kernel_idxs, &loss);
|
|
853
|
+
evoasm_deme_update_best(deme, loss, program_idx, kernel_idxs);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
return true;
|
|
859
|
+
error:
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
#define EVOASM_SORT_PAIR(t, a, b) \
|
|
864
|
+
do { \
|
|
865
|
+
t x = EVOASM_MIN(a, b); \
|
|
866
|
+
t y = EVOASM_MAX(a, b); \
|
|
867
|
+
(a) = x;\
|
|
868
|
+
(b) = y;\
|
|
869
|
+
} while(0);
|
|
870
|
+
|
|
871
|
+
typedef void (*evoasm_pop_loss_sort_func_t)(evoasm_loss_t *);
|
|
872
|
+
|
|
873
|
+
static int evoasm_pop_loss_cmp_func(const void *a, const void *b) {
|
|
874
|
+
evoasm_loss_t loss_a = *(const evoasm_loss_t *) a;
|
|
875
|
+
evoasm_loss_t loss_b = *(const evoasm_loss_t *) b;
|
|
876
|
+
return (loss_a > loss_b) - (loss_a < loss_b);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
#define EVOASM_POP_FIND_MEDIAN_RUN_LEN 8u
|
|
880
|
+
|
|
881
|
+
static inline evoasm_loss_t
|
|
882
|
+
evoasm_pop_find_median_loss_(evoasm_loss_t *losses, size_t len) {
|
|
883
|
+
|
|
884
|
+
evoasm_loss_t median;
|
|
885
|
+
assert(len >= EVOASM_DEME_MIN_LOSS_SAMPLES && len <= EVOASM_DEME_MAX_LOSS_SAMPLES);
|
|
886
|
+
|
|
887
|
+
size_t trunc_len = EVOASM_ALIGN_DOWN(len, EVOASM_POP_FIND_MEDIAN_RUN_LEN);
|
|
888
|
+
size_t n_runs = trunc_len / EVOASM_POP_FIND_MEDIAN_RUN_LEN;
|
|
889
|
+
size_t front_idxs[EVOASM_DEME_MAX_LOSS_SAMPLES / EVOASM_POP_FIND_MEDIAN_RUN_LEN] = {0};
|
|
890
|
+
evoasm_loss_t scratch[EVOASM_DEME_MAX_LOSS_SAMPLES / 2];
|
|
891
|
+
|
|
892
|
+
for(size_t i = 0; i < trunc_len; i += EVOASM_POP_FIND_MEDIAN_RUN_LEN) {
|
|
893
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 0], losses[i + 1]);
|
|
894
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 2], losses[i + 3]);
|
|
895
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 0], losses[i + 2]);
|
|
896
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 3]);
|
|
897
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 2]);
|
|
898
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 4], losses[i + 5]);
|
|
899
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 6], losses[i + 7]);
|
|
900
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 4], losses[i + 6]);
|
|
901
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 5], losses[i + 7]);
|
|
902
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 5], losses[i + 6]);
|
|
903
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 0], losses[i + 4]);
|
|
904
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 5]);
|
|
905
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 1], losses[i + 4]);
|
|
906
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 2], losses[i + 6]);
|
|
907
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 7]);
|
|
908
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 6]);
|
|
909
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 2], losses[i + 4]);
|
|
910
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 5]);
|
|
911
|
+
EVOASM_SORT_PAIR(evoasm_loss_t, losses[i + 3], losses[i + 4]);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
switch(n_runs) {
|
|
915
|
+
case 1:
|
|
916
|
+
return losses[EVOASM_POP_FIND_MEDIAN_RUN_LEN / 2 - 1];
|
|
917
|
+
case 2: {
|
|
918
|
+
const size_t merge_len = 8;
|
|
919
|
+
for(size_t i = 0; i < merge_len; i++) {
|
|
920
|
+
size_t loss_off0 = 0 * EVOASM_POP_FIND_MEDIAN_RUN_LEN + front_idxs[0];
|
|
921
|
+
size_t loss_off1 = 1 * EVOASM_POP_FIND_MEDIAN_RUN_LEN + front_idxs[1];
|
|
922
|
+
evoasm_loss_t loss0 = losses[loss_off0];
|
|
923
|
+
evoasm_loss_t loss1 = losses[loss_off1];
|
|
924
|
+
evoasm_loss_t min_loss;
|
|
925
|
+
size_t min_run_idx;
|
|
926
|
+
|
|
927
|
+
if(loss0 < loss1) {
|
|
928
|
+
min_run_idx = 0;
|
|
929
|
+
min_loss = loss0;
|
|
930
|
+
} else {
|
|
931
|
+
min_run_idx = 1;
|
|
932
|
+
min_loss = loss1;
|
|
933
|
+
}
|
|
934
|
+
front_idxs[min_run_idx]++;
|
|
935
|
+
scratch[i] = min_loss;
|
|
936
|
+
}
|
|
937
|
+
median = scratch[merge_len - 1];
|
|
938
|
+
break;
|
|
939
|
+
}
|
|
940
|
+
default:
|
|
941
|
+
evoasm_assert_not_reached();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
#ifdef EVOASM_ENABLE_PARANOID_MODE
|
|
945
|
+
evoasm_loss_t median_;
|
|
946
|
+
qsort(losses, len, sizeof(evoasm_loss_t), evoasm_pop_loss_cmp_func);
|
|
947
|
+
median_ = losses[(len - 1) / 2];
|
|
948
|
+
assert(median == median_);
|
|
949
|
+
#endif
|
|
950
|
+
|
|
951
|
+
return median;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
evoasm_loss_t
|
|
955
|
+
evoasm_pop_find_median_loss(evoasm_loss_t *losses, size_t len) {
|
|
956
|
+
return evoasm_pop_find_median_loss_(losses, len);
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
evoasm_loss_t
|
|
960
|
+
evoasm_pop_get_best_loss(evoasm_pop_t *pop) {
|
|
961
|
+
evoasm_deme_t *best_deme = evoasm_pop_find_best_deme(pop);
|
|
962
|
+
return best_deme->best_loss;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
static void
|
|
966
|
+
evoasm_deme_eval_update(evoasm_deme_t *deme) {
|
|
967
|
+
|
|
968
|
+
evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
|
|
969
|
+
|
|
970
|
+
size_t height = evoasm_pop_params_get_deme_height_(deme->params);
|
|
971
|
+
|
|
972
|
+
for(size_t i = 0; i < height; i++) {
|
|
973
|
+
deme->top_losses[i] = INFINITY;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
for(size_t i = 0; i < height; i++) {
|
|
977
|
+
for(size_t j = 0; j < deme->params->deme_size; j++) {
|
|
978
|
+
size_t indiv_off = EVOASM_DEME_INDIV_OFF(deme, i, j);
|
|
979
|
+
size_t sample0_off = EVOASM_DEME_LOSS_SAMPLE_OFF(deme, i, j, 0);
|
|
980
|
+
|
|
981
|
+
evoasm_loss_t indiv_loss =
|
|
982
|
+
evoasm_pop_find_median_loss_(&loss_data->samples[sample0_off],
|
|
983
|
+
loss_data->counters[indiv_off]);
|
|
984
|
+
|
|
985
|
+
loss_data->samples[sample0_off] = indiv_loss;
|
|
986
|
+
|
|
987
|
+
if(indiv_loss < deme->top_losses[i]) {
|
|
988
|
+
evoasm_log_info("new top loss %zu: %f -> %f", i, deme->top_losses[i], indiv_loss);
|
|
989
|
+
deme->top_losses[i] = indiv_loss;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
size_t
|
|
996
|
+
evoasm_pop_get_loss_samples(evoasm_pop_t *pop, size_t deme_idx, const evoasm_loss_t **losses) {
|
|
997
|
+
evoasm_deme_t *deme = &pop->demes[deme_idx];
|
|
998
|
+
size_t len = EVOASM_DEME_N_INDIVS(deme) * EVOASM_DEME_MAX_LOSS_SAMPLES;
|
|
999
|
+
*losses = deme->loss_data.samples;
|
|
1000
|
+
|
|
1001
|
+
return len;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
static evoasm_success_t
|
|
1005
|
+
evoasm_deme_eval(evoasm_deme_t *deme) {
|
|
1006
|
+
bool retval = true;
|
|
1007
|
+
|
|
1008
|
+
EVOASM_MEMSET_N(deme->loss_data.counters, 0, EVOASM_DEME_N_INDIVS(deme));
|
|
1009
|
+
//EVOASM_MEMSET_N(deme->loss_data.samples, 0, EVOASM_DEME_N_INDIVS(deme) * EVOASM_DEME_MAX_LOSS_SAMPLES);
|
|
1010
|
+
|
|
1011
|
+
if(deme->params->program_size > 1) {
|
|
1012
|
+
if(!evoasm_deme_test_programs(deme)) {
|
|
1013
|
+
retval = false;
|
|
1014
|
+
goto done;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
if(!evoasm_deme_test_kernels(deme)) {
|
|
1019
|
+
retval = false;
|
|
1020
|
+
goto done;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
evoasm_deme_eval_update(deme);
|
|
1024
|
+
|
|
1025
|
+
done:
|
|
1026
|
+
return retval;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
evoasm_success_t
|
|
1030
|
+
evoasm_pop_eval(evoasm_pop_t *pop) {
|
|
1031
|
+
bool retval = true;
|
|
1032
|
+
size_t n_demes = pop->params->n_demes;
|
|
1033
|
+
|
|
1034
|
+
if(!pop->seeded) {
|
|
1035
|
+
retval = false;
|
|
1036
|
+
evoasm_error(EVOASM_ERROR_TYPE_POP, EVOASM_ERROR_CODE_NONE,
|
|
1037
|
+
"not seeded");
|
|
1038
|
+
goto done;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
bool *retvals = evoasm_alloca(sizeof(bool) * n_demes);
|
|
1042
|
+
evoasm_error_t *errors = evoasm_alloca(sizeof(evoasm_error_t) * n_demes);
|
|
1043
|
+
|
|
1044
|
+
#pragma omp parallel for
|
|
1045
|
+
for(size_t i = 0; i < n_demes; i++) {
|
|
1046
|
+
retvals[i] = evoasm_deme_eval(&pop->demes[i]);
|
|
1047
|
+
if(!retvals[i]) {
|
|
1048
|
+
errors[i] = *evoasm_get_last_error();
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
for(size_t i = 0; i < n_demes; i++) {
|
|
1053
|
+
if(!retvals[i]) {
|
|
1054
|
+
evoasm_set_last_error(&errors[i]);
|
|
1055
|
+
retval = false;
|
|
1056
|
+
break;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
done:
|
|
1061
|
+
return retval;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
static inline void
|
|
1066
|
+
evoasm_deme_select_indivs(evoasm_deme_t *deme, size_t row, bool programs) {
|
|
1067
|
+
evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
|
|
1068
|
+
size_t n_doomed_indivs = 0;
|
|
1069
|
+
size_t n_blessed_indivs = 0;
|
|
1070
|
+
size_t deme_size = deme->params->deme_size;
|
|
1071
|
+
|
|
1072
|
+
|
|
1073
|
+
size_t n = 1;
|
|
1074
|
+
evoasm_loss_t avg_loss = 0.0;
|
|
1075
|
+
for(size_t i = 0; i < deme_size; i++) {
|
|
1076
|
+
evoasm_loss_t loss = loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, i)];
|
|
1077
|
+
if(!isinf(loss)) {
|
|
1078
|
+
avg_loss += (loss - avg_loss) / (evoasm_loss_t) n;
|
|
1079
|
+
n++;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
avg_loss += 0.0001f;
|
|
1084
|
+
for(size_t i = 0; i < deme_size; i++) {
|
|
1085
|
+
evoasm_loss_t loss = loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, i)];
|
|
1086
|
+
|
|
1087
|
+
if(loss > avg_loss) {
|
|
1088
|
+
deme->doomed_indiv_idxs[n_doomed_indivs++] = (uint16_t) i;
|
|
1089
|
+
} else {
|
|
1090
|
+
deme->blessed_indiv_idxs[n_blessed_indivs++] = (uint16_t) i;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
assert(n_blessed_indivs > 0);
|
|
1095
|
+
assert(n_doomed_indivs > 0);
|
|
1096
|
+
|
|
1097
|
+
deme->n_blessed_indivs = (uint16_t) n_blessed_indivs;
|
|
1098
|
+
deme->n_doomed_indivs = (uint16_t) n_doomed_indivs;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
static size_t
|
|
1102
|
+
evoasm_deme_get_indiv_size(evoasm_deme_t *deme, bool programs) {
|
|
1103
|
+
return programs ? deme->params->program_size : deme->params->kernel_size;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
static evoasm_force_inline inline void
|
|
1107
|
+
evoasm_deme_combine_indivs(evoasm_deme_t *deme, size_t row, size_t idx, bool programs) {
|
|
1108
|
+
evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
|
|
1109
|
+
evoasm_pop_program_data_t *program_data = &deme->program_data;
|
|
1110
|
+
evoasm_pop_kernel_data_t *kernel_data = &deme->kernel_data;
|
|
1111
|
+
evoasm_prng_t *prng = &deme->prng;
|
|
1112
|
+
|
|
1113
|
+
size_t indiv_size = evoasm_deme_get_indiv_size(deme, programs);
|
|
1114
|
+
|
|
1115
|
+
size_t parent_idxs[2] = {
|
|
1116
|
+
deme->blessed_indiv_idxs[idx % deme->n_blessed_indivs],
|
|
1117
|
+
deme->blessed_indiv_idxs[(idx + 1) % deme->n_blessed_indivs]
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
size_t child_idxs[2] = {
|
|
1121
|
+
deme->doomed_indiv_idxs[idx],
|
|
1122
|
+
deme->doomed_indiv_idxs[idx + 1]
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1125
|
+
/* rough estimate */
|
|
1126
|
+
evoasm_loss_t child_loss = 0.5f * loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, parent_idxs[0])]
|
|
1127
|
+
+ 0.5f * loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, parent_idxs[1])];
|
|
1128
|
+
|
|
1129
|
+
assert(isfinite(child_loss));
|
|
1130
|
+
|
|
1131
|
+
float crossover_point = evoasm_prng_randf_(prng);
|
|
1132
|
+
size_t seg1_len = EVOASM_MAX(1u, (size_t) (crossover_point * (float) indiv_size));
|
|
1133
|
+
size_t seg2_len = indiv_size - seg1_len;
|
|
1134
|
+
|
|
1135
|
+
for(size_t j = 0; j < 2; j++) {
|
|
1136
|
+
loss_data->samples[EVOASM_DEME_LOSS_OFF(deme, row, child_idxs[j])] = child_loss;
|
|
1137
|
+
|
|
1138
|
+
if(programs) {
|
|
1139
|
+
size_t parent_pos0_offs[] = {
|
|
1140
|
+
EVOASM_DEME_PROGRAM_POS_OFF(deme, parent_idxs[j], 0),
|
|
1141
|
+
EVOASM_DEME_PROGRAM_POS_OFF(deme, parent_idxs[1 - j], 0)
|
|
1142
|
+
};
|
|
1143
|
+
|
|
1144
|
+
size_t child_pos0_off = EVOASM_DEME_PROGRAM_POS_OFF(deme, child_idxs[j], 0);
|
|
1145
|
+
|
|
1146
|
+
evoasm_pop_program_data_copy(program_data, parent_pos0_offs[0],
|
|
1147
|
+
program_data, child_pos0_off, seg1_len);
|
|
1148
|
+
evoasm_pop_program_data_copy(program_data, parent_pos0_offs[1] + seg1_len,
|
|
1149
|
+
program_data, child_pos0_off + seg1_len, seg2_len);
|
|
1150
|
+
|
|
1151
|
+
} else {
|
|
1152
|
+
size_t parent_inst0_offs [] = {
|
|
1153
|
+
EVOASM_DEME_KERNEL_INST_OFF(deme, row, parent_idxs[j], 0),
|
|
1154
|
+
EVOASM_DEME_KERNEL_INST_OFF(deme, row, parent_idxs[1 - j], 0)
|
|
1155
|
+
};
|
|
1156
|
+
size_t child_inst0_off = EVOASM_DEME_KERNEL_INST_OFF(deme, row, child_idxs[j], 0);
|
|
1157
|
+
|
|
1158
|
+
evoasm_pop_kernel_data_copy(kernel_data, deme->arch_id, parent_inst0_offs[0],
|
|
1159
|
+
kernel_data, child_inst0_off, seg1_len);
|
|
1160
|
+
evoasm_pop_kernel_data_copy(kernel_data, deme->arch_id, parent_inst0_offs[1] + seg1_len,
|
|
1161
|
+
kernel_data, child_inst0_off + seg1_len, seg2_len);
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
static evoasm_force_inline inline void
|
|
1167
|
+
evoasm_deme_combine(evoasm_deme_t *deme, size_t row, bool programs) {
|
|
1168
|
+
for(size_t i = 0; i < deme->n_doomed_indivs; i += 2) {
|
|
1169
|
+
evoasm_deme_combine_indivs(deme, row, i, programs);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
static inline void
|
|
1174
|
+
evoasm_deme_calc_summary(evoasm_deme_t *deme, evoasm_loss_t *summary_losses, evoasm_loss_t *summary) {
|
|
1175
|
+
size_t deme_size = deme->params->deme_size;
|
|
1176
|
+
evoasm_pop_loss_data_t *loss_data = &deme->loss_data;
|
|
1177
|
+
|
|
1178
|
+
size_t height = evoasm_pop_params_get_deme_height_(deme->params);
|
|
1179
|
+
|
|
1180
|
+
for(size_t i = 0; i < height; i++) {
|
|
1181
|
+
size_t summary_off = i * 5;
|
|
1182
|
+
|
|
1183
|
+
for(size_t j = 0; j < deme_size; j++) {
|
|
1184
|
+
size_t loss_off = EVOASM_DEME_LOSS_OFF(deme, i, j);
|
|
1185
|
+
evoasm_loss_t loss = loss_data->samples[loss_off];
|
|
1186
|
+
summary_losses[j] = loss;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
qsort(summary_losses, deme_size, sizeof(evoasm_loss_t), evoasm_pop_loss_cmp_func);
|
|
1190
|
+
|
|
1191
|
+
for(size_t j = 0; j < 5; j++) {
|
|
1192
|
+
summary[summary_off + j] = summary_losses[j * (deme_size - 1) / 4];
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
#define EVOASM_DEME_SUMMARY_LEN(pop) (5 * (evoasm_pop_params_get_deme_height_(pop->params)))
|
|
1198
|
+
|
|
1199
|
+
size_t
|
|
1200
|
+
evoasm_pop_summary_len(evoasm_pop_t *pop) {
|
|
1201
|
+
return pop->params->n_demes * EVOASM_DEME_SUMMARY_LEN(pop);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
evoasm_success_t
|
|
1205
|
+
evoasm_pop_calc_summary(evoasm_pop_t *pop, evoasm_loss_t *summary) {
|
|
1206
|
+
|
|
1207
|
+
const size_t deme_summary_len = EVOASM_DEME_SUMMARY_LEN(pop);
|
|
1208
|
+
|
|
1209
|
+
if(pop->summary_losses == NULL) {
|
|
1210
|
+
pop->summary_losses = evoasm_calloc(pop->params->deme_size, sizeof(evoasm_loss_t));
|
|
1211
|
+
if(!pop->summary_losses) {
|
|
1212
|
+
return false;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
for(size_t i = 0; i < pop->params->n_demes; i++) {
|
|
1217
|
+
evoasm_deme_calc_summary(&pop->demes[i], pop->summary_losses, &summary[i * deme_summary_len]);
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
return true;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
#if 0
|
|
1225
|
+
size_t i;
|
|
1226
|
+
double scale = 1.0 / pop->params->size;
|
|
1227
|
+
double pop_loss = 0.0;
|
|
1228
|
+
*n_invalid = 0;
|
|
1229
|
+
for(i = 0; i < pop->params->size; i++) {
|
|
1230
|
+
double loss = pop->top_losses[i];
|
|
1231
|
+
if(loss != INFINITY) {
|
|
1232
|
+
pop_loss += scale * loss;
|
|
1233
|
+
} else {
|
|
1234
|
+
(*n_invalid)++;
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
if(per_example) pop_loss /= pop->n_examples;
|
|
1239
|
+
#endif
|
|
1240
|
+
|
|
1241
|
+
static evoasm_force_inline inline void
|
|
1242
|
+
evoasm_deme_mutate_indiv(evoasm_deme_t *deme, size_t row, size_t indiv_idx, bool program) {
|
|
1243
|
+
evoasm_prng_t *prng = &deme->prng;
|
|
1244
|
+
size_t indiv_size = evoasm_deme_get_indiv_size(deme, program);
|
|
1245
|
+
|
|
1246
|
+
if(evoasm_prng_randf_(prng) < deme->params->mut_rate) {
|
|
1247
|
+
uint64_t r = evoasm_prng_rand64_(prng);
|
|
1248
|
+
size_t elem_idx = (r % indiv_size);
|
|
1249
|
+
|
|
1250
|
+
if(program) {
|
|
1251
|
+
evoasm_deme_seed_program_pos(deme, indiv_idx, elem_idx);
|
|
1252
|
+
} else {
|
|
1253
|
+
evoasm_deme_seed_kernel_inst(deme, row, indiv_idx, elem_idx);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
static evoasm_force_inline inline void
|
|
1259
|
+
evoasm_deme_mutate(evoasm_deme_t *deme, size_t row, bool programs) {
|
|
1260
|
+
for(size_t i = 0; i < deme->params->deme_size; i++) {
|
|
1261
|
+
evoasm_deme_mutate_indiv(deme, row, i, programs);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
static void
|
|
1266
|
+
evoasm_deme_next_gen(evoasm_deme_t *deme) {
|
|
1267
|
+
for(size_t i = 0; i < deme->params->program_size; i++) {
|
|
1268
|
+
evoasm_deme_select_indivs(deme, i, false);
|
|
1269
|
+
evoasm_deme_combine(deme, i, false);
|
|
1270
|
+
if(deme->params->mut_rate > 0) {
|
|
1271
|
+
evoasm_deme_mutate(deme, i, false);
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
if(deme->params->program_size > 1) {
|
|
1276
|
+
evoasm_deme_select_indivs(deme, EVOASM_DEME_PROGRAMS_ROW(deme), true);
|
|
1277
|
+
evoasm_deme_combine(deme, EVOASM_DEME_PROGRAMS_ROW(deme), true);
|
|
1278
|
+
|
|
1279
|
+
if(deme->params->mut_rate > 0) {
|
|
1280
|
+
evoasm_deme_mutate(deme, EVOASM_DEME_PROGRAMS_ROW(deme), true);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
void
|
|
1286
|
+
evoasm_pop_next_gen(evoasm_pop_t *pop) {
|
|
1287
|
+
#pragma omp parallel for
|
|
1288
|
+
for(size_t i = 0; i < pop->params->n_demes; i++) {
|
|
1289
|
+
evoasm_deme_next_gen(&pop->demes[i]);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
#if 0
|
|
1294
|
+
|
|
1295
|
+
evoasm_pop_select(pop, blessed_indiv_idxs, pop->params->size);
|
|
1296
|
+
{
|
|
1297
|
+
double scale = 1.0 / pop->params->size;
|
|
1298
|
+
double pop_loss = 0.0;
|
|
1299
|
+
size_t n_inf = 0;
|
|
1300
|
+
for(i = 0; i < pop->params->size; i++) {
|
|
1301
|
+
double loss = pop->pop.top_losses[blessed_indiv_idxs[i]];
|
|
1302
|
+
if(loss != INFINITY) {
|
|
1303
|
+
pop_loss += scale * loss;
|
|
1304
|
+
}
|
|
1305
|
+
else {
|
|
1306
|
+
n_inf++;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
evoasm_log_info("pop selected loss: %g/%u", pop_loss, n_inf);
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
size_t i;
|
|
1314
|
+
for(i = 0; i < pop->params->size; i++) {
|
|
1315
|
+
evoasm_program_params_t *program_params = EVOASM_SEARCH_PROGRAM_PARAMS(pop, pop->pop.indivs, blessed_indiv_idxs[i]);
|
|
1316
|
+
assert(program_params->size > 0);
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
return evoasm_pop_combine_parents(pop, blessed_indiv_idxs);
|
|
1320
|
+
}
|
|
1321
|
+
#endif
|
|
1322
|
+
|
|
1323
|
+
EVOASM_DEF_ALLOC_FREE_FUNCS(pop)
|