evoasm 0.0.2.pre7 → 0.1.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/.gdbinit +41 -0
  3. data/.gitignore +1 -2
  4. data/.gitmodules +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +660 -0
  8. data/Makefile +1 -1
  9. data/README.md +17 -9
  10. data/Rakefile +39 -107
  11. data/bin/gdb +1 -1
  12. data/bin/gdb_loop +4 -0
  13. data/docs/FindingInstructions.md +17 -0
  14. data/docs/JIT.md +14 -0
  15. data/docs/SymbolicRegression.md +102 -0
  16. data/docs/Visualization.md +29 -0
  17. data/docs/examples/bit_insts.rb +44 -0
  18. data/docs/examples/jit.rb +26 -0
  19. data/docs/examples/loss.gif +0 -0
  20. data/docs/examples/program.png +0 -0
  21. data/docs/examples/sym_reg.rb +64 -0
  22. data/docs/examples/vis.rb +38 -0
  23. data/evoasm.gemspec +21 -15
  24. data/ext/evoasm_ext/Rakefile +3 -0
  25. data/ext/evoasm_ext/compile.rake +35 -0
  26. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
  27. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
  28. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
  29. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
  30. data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
  31. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
  32. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
  33. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
  34. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
  35. data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
  36. data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
  37. data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
  38. data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
  39. data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
  40. data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
  41. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
  42. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
  43. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
  44. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
  45. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
  46. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
  47. data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
  48. data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
  49. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
  50. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
  51. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
  52. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
  53. data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
  54. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
  55. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
  56. data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
  57. data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
  58. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
  59. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
  60. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
  61. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
  62. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
  63. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
  64. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
  65. data/lib/evoasm.rb +28 -11
  66. data/lib/evoasm/buffer.rb +105 -0
  67. data/lib/evoasm/capstone.rb +100 -0
  68. data/lib/evoasm/domain.rb +116 -0
  69. data/lib/evoasm/error.rb +37 -16
  70. data/lib/evoasm/exception_error.rb +19 -0
  71. data/lib/evoasm/ffi_ext.rb +53 -0
  72. data/lib/evoasm/libevoasm.rb +286 -0
  73. data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
  74. data/lib/evoasm/parameter.rb +20 -0
  75. data/lib/evoasm/population.rb +145 -0
  76. data/lib/evoasm/population/parameters.rb +227 -0
  77. data/lib/evoasm/population/plotter.rb +89 -0
  78. data/lib/evoasm/prng.rb +64 -0
  79. data/lib/evoasm/program.rb +195 -12
  80. data/lib/evoasm/program/io.rb +144 -0
  81. data/lib/evoasm/test.rb +8 -0
  82. data/lib/evoasm/version.rb +1 -1
  83. data/lib/evoasm/x64.rb +115 -0
  84. data/lib/evoasm/x64/cpu_state.rb +95 -0
  85. data/lib/evoasm/x64/instruction.rb +109 -0
  86. data/lib/evoasm/x64/operand.rb +156 -0
  87. data/lib/evoasm/x64/parameters.rb +211 -0
  88. data/test/helpers/population_helper.rb +128 -0
  89. data/test/helpers/test_helper.rb +1 -0
  90. data/test/helpers/x64_helper.rb +24 -0
  91. data/test/integration/bitwise_reverse_test.rb +41 -0
  92. data/test/integration/gcd_test.rb +52 -0
  93. data/test/integration/popcnt_test.rb +46 -0
  94. data/test/integration/sym_reg_test.rb +68 -0
  95. data/test/unit/evoasm/buffer_test.rb +48 -0
  96. data/test/unit/evoasm/capstone_test.rb +18 -0
  97. data/test/unit/evoasm/domain_test.rb +55 -0
  98. data/test/unit/evoasm/population/parameters_test.rb +106 -0
  99. data/test/unit/evoasm/population_test.rb +96 -0
  100. data/test/unit/evoasm/prng_test.rb +47 -0
  101. data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
  102. data/test/unit/evoasm/x64/encoding_test.rb +320 -0
  103. data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
  104. data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
  105. data/test/unit/evoasm/x64/instruction_test.rb +62 -0
  106. data/test/unit/evoasm/x64/parameters_test.rb +65 -0
  107. data/test/unit/evoasm/x64_test.rb +52 -0
  108. metadata +195 -89
  109. data/Gemfile.rake +0 -8
  110. data/Gemfile.rake.lock +0 -51
  111. data/LICENSE.txt +0 -373
  112. data/data/tables/README.md +0 -19
  113. data/data/tables/x64.csv +0 -1684
  114. data/data/templates/evoasm-x64.c.erb +0 -319
  115. data/data/templates/evoasm-x64.h.erb +0 -126
  116. data/examples/abs.yml +0 -20
  117. data/examples/popcnt.yml +0 -17
  118. data/examples/sym_reg.yml +0 -26
  119. data/exe/evoasm-search +0 -13
  120. data/ext/evoasm_ext/evoasm-alloc.c +0 -145
  121. data/ext/evoasm_ext/evoasm-alloc.h +0 -59
  122. data/ext/evoasm_ext/evoasm-arch.c +0 -44
  123. data/ext/evoasm_ext/evoasm-arch.h +0 -161
  124. data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
  125. data/ext/evoasm_ext/evoasm-buf.c +0 -130
  126. data/ext/evoasm_ext/evoasm-buf.h +0 -47
  127. data/ext/evoasm_ext/evoasm-error.c +0 -31
  128. data/ext/evoasm_ext/evoasm-error.h +0 -75
  129. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
  130. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
  131. data/ext/evoasm_ext/evoasm-log.h +0 -69
  132. data/ext/evoasm_ext/evoasm-misc.c +0 -23
  133. data/ext/evoasm_ext/evoasm-misc.h +0 -282
  134. data/ext/evoasm_ext/evoasm-param.h +0 -37
  135. data/ext/evoasm_ext/evoasm-search.c +0 -2145
  136. data/ext/evoasm_ext/evoasm-search.h +0 -214
  137. data/ext/evoasm_ext/evoasm-util.h +0 -40
  138. data/ext/evoasm_ext/evoasm-x64.c +0 -275624
  139. data/ext/evoasm_ext/evoasm-x64.h +0 -5436
  140. data/ext/evoasm_ext/evoasm.c +0 -7
  141. data/ext/evoasm_ext/evoasm.h +0 -23
  142. data/ext/evoasm_ext/evoasm_ext.c +0 -1757
  143. data/ext/evoasm_ext/extconf.rb +0 -31
  144. data/lib/evoasm/cli.rb +0 -6
  145. data/lib/evoasm/cli/search.rb +0 -127
  146. data/lib/evoasm/core_ext.rb +0 -1
  147. data/lib/evoasm/core_ext/array.rb +0 -9
  148. data/lib/evoasm/core_ext/integer.rb +0 -10
  149. data/lib/evoasm/core_ext/kwstruct.rb +0 -13
  150. data/lib/evoasm/core_ext/range.rb +0 -5
  151. data/lib/evoasm/examples.rb +0 -27
  152. data/lib/evoasm/gen.rb +0 -8
  153. data/lib/evoasm/gen/enum.rb +0 -169
  154. data/lib/evoasm/gen/name_util.rb +0 -80
  155. data/lib/evoasm/gen/state.rb +0 -176
  156. data/lib/evoasm/gen/state_dsl.rb +0 -152
  157. data/lib/evoasm/gen/strio.rb +0 -27
  158. data/lib/evoasm/gen/translator.rb +0 -1102
  159. data/lib/evoasm/gen/version.rb +0 -5
  160. data/lib/evoasm/gen/x64.rb +0 -237
  161. data/lib/evoasm/gen/x64/funcs.rb +0 -495
  162. data/lib/evoasm/gen/x64/inst.rb +0 -781
  163. data/lib/evoasm/search.rb +0 -40
  164. data/lib/evoasm/tasks/gen_task.rb +0 -86
  165. data/lib/evoasm/tasks/template_task.rb +0 -52
  166. data/test/test_helper.rb +0 -1
  167. data/test/x64/test_helper.rb +0 -19
  168. 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, &params->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)