Punishment update
This commit is contained in:
@@ -39,6 +39,7 @@ constexpr int ID_MINUTES = 1003;
|
||||
constexpr int ID_TOPOLOGY_FROM = 1004;
|
||||
constexpr int ID_TOPOLOGY_TO = 1005;
|
||||
constexpr int ID_CHECKPOINT_SECONDS = 1006;
|
||||
constexpr int ID_SEARCH_MODE = 1007;
|
||||
constexpr int ID_START = 2001;
|
||||
constexpr int ID_STOP = 2002;
|
||||
|
||||
@@ -59,6 +60,7 @@ HWND g_minutes = nullptr;
|
||||
HWND g_topology_from = nullptr;
|
||||
HWND g_topology_to = nullptr;
|
||||
HWND g_checkpoint_seconds = nullptr;
|
||||
HWND g_search_mode = nullptr;
|
||||
std::vector<HWND> g_setting_controls;
|
||||
|
||||
HFONT g_ui_font = nullptr;
|
||||
@@ -569,6 +571,28 @@ HWND make_button(
|
||||
return control;
|
||||
}
|
||||
|
||||
HWND make_search_mode_combo(HWND parent, int x, int y, int width, int height) {
|
||||
HWND control = CreateWindowExW(
|
||||
0,
|
||||
L"COMBOBOX",
|
||||
L"",
|
||||
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
parent,
|
||||
reinterpret_cast<HMENU>(static_cast<INT_PTR>(ID_SEARCH_MODE)),
|
||||
nullptr,
|
||||
nullptr);
|
||||
SendMessageW(control, WM_SETFONT, reinterpret_cast<WPARAM>(g_ui_font), TRUE);
|
||||
SendMessageW(control, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Обычный"));
|
||||
SendMessageW(control, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(L"Проработка худших"));
|
||||
SendMessageW(control, CB_SETCURSEL, 0, 0);
|
||||
g_setting_controls.push_back(control);
|
||||
return control;
|
||||
}
|
||||
|
||||
void create_controls(HWND window) {
|
||||
g_title_font = CreateFontW(
|
||||
24, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET,
|
||||
@@ -606,6 +630,9 @@ void create_controls(HWND window) {
|
||||
g_checkpoint_seconds =
|
||||
make_number_edit(window, ID_CHECKPOINT_SECONDS, L"30", 592, 110, 125, 27);
|
||||
|
||||
make_label(window, L"Режим поиска", 735, 86, 245, 22);
|
||||
g_search_mode = make_search_mode_combo(window, 735, 110, 245, 180);
|
||||
|
||||
make_label(
|
||||
window,
|
||||
L"CUDA-устройство выбирается автоматически. Поиск: FP32; финальная проверка кандидатов: DD.",
|
||||
@@ -688,26 +715,37 @@ void start_search() {
|
||||
const int seed = make_automatic_seed();
|
||||
append_log_direct(L"Seed запуска: " + std::to_wstring(seed));
|
||||
|
||||
const bool prioritize_worst =
|
||||
SendMessageW(g_search_mode, CB_GETCURSEL, 0, 0) == 1;
|
||||
append_log_direct(
|
||||
prioritize_worst
|
||||
? L"Режим поиска: проработка худших вариантов."
|
||||
: L"Режим поиска: обычный.");
|
||||
|
||||
const fs::path stop_path = make_stop_path();
|
||||
const std::wstring title =
|
||||
L"CUDA-поиск, топологии " + std::to_wstring(topology_from) +
|
||||
L"–" + std::to_wstring(topology_to);
|
||||
std::vector<std::wstring> args{
|
||||
L"--global-search",
|
||||
L"--cuda",
|
||||
L"--seed", std::to_wstring(seed),
|
||||
L"--cuda-chains", std::to_wstring(cuda_chains),
|
||||
L"--cuda-iters", std::to_wstring(cuda_iters),
|
||||
L"--minutes", std::to_wstring(minutes),
|
||||
L"--topology-from", std::to_wstring(topology_from),
|
||||
L"--topology-to", std::to_wstring(topology_to),
|
||||
L"--checkpoint-seconds", std::to_wstring(checkpoint_seconds),
|
||||
L"--stop-file", stop_path.wstring(),
|
||||
L"--global-dir", L"results\\search"
|
||||
};
|
||||
if (prioritize_worst) {
|
||||
args.push_back(L"--prioritize-worst");
|
||||
}
|
||||
start_process(
|
||||
title,
|
||||
main_exe(),
|
||||
{
|
||||
L"--global-search",
|
||||
L"--cuda",
|
||||
L"--seed", std::to_wstring(seed),
|
||||
L"--cuda-chains", std::to_wstring(cuda_chains),
|
||||
L"--cuda-iters", std::to_wstring(cuda_iters),
|
||||
L"--minutes", std::to_wstring(minutes),
|
||||
L"--topology-from", std::to_wstring(topology_from),
|
||||
L"--topology-to", std::to_wstring(topology_to),
|
||||
L"--checkpoint-seconds", std::to_wstring(checkpoint_seconds),
|
||||
L"--stop-file", stop_path.wstring(),
|
||||
L"--global-dir", L"results\\search"
|
||||
},
|
||||
args,
|
||||
stop_path);
|
||||
}
|
||||
|
||||
|
||||
+120
-21
@@ -42,7 +42,8 @@
|
||||
#define NUM_TOPOLOGIES 59
|
||||
#define DUAL_PROBLEM 0
|
||||
constexpr int GLOBAL_PLANE_VALUE_COUNT = 36;
|
||||
constexpr std::uint32_t GLOBAL_OBJECTIVE_VERSION = 3;
|
||||
constexpr std::uint32_t GLOBAL_OBJECTIVE_VERSION = 4;
|
||||
constexpr std::uint32_t MIN_COMPATIBLE_ARCHIVE_OBJECTIVE_VERSION = 3;
|
||||
constexpr int CUDA_SESSION_CACHE_LIMIT = NUM_TOPOLOGIES;
|
||||
|
||||
struct StudyOptions {
|
||||
@@ -86,7 +87,8 @@ struct LocalRepairOptions {
|
||||
int cuda_chains = 0;
|
||||
int cuda_iterations = 64;
|
||||
int checkpoint_seconds = 30;
|
||||
double degeneracy_weight = 0.02;
|
||||
double degeneracy_weight = 0.01;
|
||||
bool prioritize_worst = false;
|
||||
bool use_cuda = false;
|
||||
};
|
||||
|
||||
@@ -152,7 +154,8 @@ void print_usage(const char* exe_name) {
|
||||
<< " --cuda-chains <n> Parallel GPU chains. 0 = automatic (default).\n"
|
||||
<< " --cuda-iters <n> Iterations per short GPU batch. Default: 64\n"
|
||||
<< " --checkpoint-seconds <n> Durable checkpoint period. Default: 30\n"
|
||||
<< " --degeneracy-weight <x> Degenerate-geometry penalty. Default: 0.02\n"
|
||||
<< " --degeneracy-weight <x> Worst-barrier degeneracy penalty. Default: 0.01\n"
|
||||
<< " --prioritize-worst Give depth priority to the worst current topologies.\n"
|
||||
<< " --start-planes <p> Continue batch-hunt from a saved .planes sidecar.\n"
|
||||
<< " --restarts <n> hunt-local restarts. Default: 256\n"
|
||||
<< " --stagnation <n> Iterations before hunt-local reheat. Default: 2000\n"
|
||||
@@ -2213,7 +2216,7 @@ struct GlobalMetrics {
|
||||
bool precise = false;
|
||||
};
|
||||
|
||||
double g_global_degeneracy_weight = 0.02;
|
||||
double g_global_degeneracy_weight = 0.01;
|
||||
std::string g_search_device_id = "CPU";
|
||||
|
||||
std::uint64_t topology_fingerprint() {
|
||||
@@ -2446,18 +2449,54 @@ bool add_global_archive_elite(
|
||||
return retained;
|
||||
}
|
||||
|
||||
double topology_scheduler_severity(const GlobalMetrics& metrics) {
|
||||
return static_cast<double>(global_defects(metrics)) +
|
||||
0.10 * static_cast<double>(std::max(metrics.crossings, metrics.intersections)) +
|
||||
0.01 * static_cast<double>(metrics.crossings);
|
||||
}
|
||||
|
||||
double topology_scheduler_worstness(
|
||||
const GlobalTopologyState& state,
|
||||
double best_severity,
|
||||
double worst_severity
|
||||
) {
|
||||
if (!state.has_state) {
|
||||
return 1.0;
|
||||
}
|
||||
const double span = worst_severity - best_severity;
|
||||
if (span <= 1.0e-9) {
|
||||
return 0.0;
|
||||
}
|
||||
return std::clamp(
|
||||
(topology_scheduler_severity(state.best) - best_severity) / span,
|
||||
0.0,
|
||||
1.0);
|
||||
}
|
||||
|
||||
double topology_bandit_score(
|
||||
const GlobalTopologyState& state,
|
||||
std::uint64_t total_pulls,
|
||||
std::uint64_t current_round,
|
||||
int best_defects
|
||||
double best_severity,
|
||||
double worst_severity,
|
||||
int best_defects,
|
||||
bool prioritize_worst
|
||||
) {
|
||||
const double exploration = 0.60 * std::sqrt(
|
||||
std::log(static_cast<double>(total_pulls) + 2.0) /
|
||||
(static_cast<double>(state.scheduler_pulls) + 1.0));
|
||||
const double quality_prior = state.has_state
|
||||
? 0.30 / (1.0 + std::max(0, global_defects(state.best) - best_defects))
|
||||
: 0.35;
|
||||
double quality_prior = prioritize_worst ? 0.70 : 0.35;
|
||||
if (state.has_state) {
|
||||
if (prioritize_worst) {
|
||||
quality_prior = 0.65 * topology_scheduler_worstness(
|
||||
state,
|
||||
best_severity,
|
||||
worst_severity);
|
||||
} else {
|
||||
quality_prior = 0.30 /
|
||||
(1.0 + std::max(0, global_defects(state.best) - best_defects));
|
||||
}
|
||||
}
|
||||
const double rounds_since_pull = state.scheduler_last_pull == 0
|
||||
? static_cast<double>(current_round + 1)
|
||||
: static_cast<double>(current_round - state.scheduler_last_pull);
|
||||
@@ -2695,12 +2734,20 @@ GlobalMetrics evaluate_global_state(
|
||||
const double turn_barrier =
|
||||
std::log1p(0.002 / std::max(1e-10, min_turn_sine));
|
||||
const double extent_barrier = 0.10 * std::log1p(max_vertex_norm / 100.0);
|
||||
const double worst_degeneracy_barrier = std::max({
|
||||
determinant_barrier,
|
||||
edge_barrier,
|
||||
turn_barrier,
|
||||
extent_barrier});
|
||||
const double secondary_degeneracy_barriers =
|
||||
determinant_barrier + edge_barrier + turn_barrier + extent_barrier -
|
||||
worst_degeneracy_barrier;
|
||||
metrics.min_plane_determinant = min_plane_determinant;
|
||||
metrics.relative_min_edge = relative_min_edge;
|
||||
metrics.min_turn_sine = min_turn_sine;
|
||||
metrics.max_vertex_norm = max_vertex_norm;
|
||||
metrics.degeneracy_penalty = g_global_degeneracy_weight *
|
||||
(determinant_barrier + edge_barrier + turn_barrier + extent_barrier);
|
||||
(worst_degeneracy_barrier + 0.05 * secondary_degeneracy_barriers);
|
||||
metrics.geometry_penalty =
|
||||
0.0010 * std::min(20.0, std::log1p(condition)) +
|
||||
0.0002 * std::min(20.0, std::log1p(max_vertex_norm)) +
|
||||
@@ -3306,7 +3353,9 @@ void load_mergeable_checkpoints(
|
||||
if (record.delta.topology != topology) {
|
||||
continue;
|
||||
}
|
||||
if (record.delta.objective_version != GLOBAL_OBJECTIVE_VERSION ||
|
||||
if (record.delta.objective_version <
|
||||
MIN_COMPATIBLE_ARCHIVE_OBJECTIVE_VERSION ||
|
||||
record.delta.objective_version > GLOBAL_OBJECTIVE_VERSION ||
|
||||
record.delta.topology_fingerprint != expected_fingerprint) {
|
||||
incompatible_archive_deltas += 1;
|
||||
continue;
|
||||
@@ -3641,13 +3690,14 @@ bool write_run_manifest(
|
||||
std::cerr << "Cannot write run manifest: " << manifest_path << std::endl;
|
||||
return false;
|
||||
}
|
||||
out << "format\tszilassi-global-search-v3\n"
|
||||
out << "format\tszilassi-global-search-v4\n"
|
||||
<< "run_id\t" << identity.run_id << "\n"
|
||||
<< "node_id\t" << identity.node_id << "\n"
|
||||
<< "seed\t" << options.seed << "\n"
|
||||
<< "topology_from\t" << options.topology_from << "\n"
|
||||
<< "topology_to\t" << options.topology_to << "\n"
|
||||
<< "backend\t" << (options.use_cuda ? "cuda-fp32" : "cpu-double") << "\n"
|
||||
<< "objective_version\t" << GLOBAL_OBJECTIVE_VERSION << "\n"
|
||||
<< "cuda_math\tstandard-fp32\n"
|
||||
<< "cuda_chains_requested\t" << options.cuda_chains << "\n"
|
||||
<< "cuda_chains_effective\t" << effective_cuda_chains << "\n"
|
||||
@@ -3666,8 +3716,12 @@ bool write_run_manifest(
|
||||
<< "map_elites_max_cells_per_topology\t4096\n"
|
||||
<< "cem\tdiagonal-weighted,covariance-adaptation:0.18,new-injected-only\n"
|
||||
<< "spsa\tadam:6,cpu-double,fp32-roundtrip,final-canonical-dd-gate\n"
|
||||
<< "topology_scheduler\tucb-plus-quality,full-refresh-every-5\n"
|
||||
<< "topology_scheduler\tucb-plus-reward-plus-staleness,full-refresh-every-5\n"
|
||||
<< "topology_scheduler_mode\t"
|
||||
<< (options.prioritize_worst ? "worst-first" : "quality-first") << "\n"
|
||||
<< "worst_priority_coefficient\t0.65\n"
|
||||
<< "cpu_iterations_per_trial\t" << options.iterations << "\n"
|
||||
<< "degeneracy_formula\tworst-plus-0.05-rest\n"
|
||||
<< "degeneracy_weight\t" << std::setprecision(17)
|
||||
<< options.degeneracy_weight << "\n";
|
||||
out.flush();
|
||||
@@ -4208,6 +4262,8 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
<< ", run " << run_identity.run_id
|
||||
<< ", node " << run_identity.node_id
|
||||
<< ", threads " << worker_count
|
||||
<< ", scheduler "
|
||||
<< (options.prioritize_worst ? "worst-first" : "quality-first")
|
||||
<< ", minutes " << (options.time_limit_seconds / 60.0)
|
||||
<< " ===\n";
|
||||
std::ofstream metrics_log(
|
||||
@@ -4222,7 +4278,7 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
return 2;
|
||||
}
|
||||
metrics_log
|
||||
<< "round\tunix_ns\tphase\ttopology\tdepth\tbandit_score"
|
||||
<< "round\tunix_ns\tphase\ttopology\tdepth\tbandit_score\tworstness"
|
||||
<< "\tbefore_C\tbefore_I\tafter_C\tafter_I\timproved\tbackend_error"
|
||||
<< "\tarchive_cells\tarchive_improvements\tverified\taccounted_fp32_steps"
|
||||
<< "\tnew_trials\tkernel_ms\ttransfer_ms\twall_ms"
|
||||
@@ -4243,6 +4299,13 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
<< std::endl;
|
||||
std::cout << "Topologies: " << options.topology_from << ".."
|
||||
<< options.topology_to << " (" << active_topologies.size() << ")" << std::endl;
|
||||
std::cout << "Scheduler : "
|
||||
<< (options.prioritize_worst
|
||||
? "priority to the worst current topologies"
|
||||
: "priority to the most promising topologies")
|
||||
<< std::endl;
|
||||
std::cout << "Degenerate: worst barrier + 5% of the rest, weight "
|
||||
<< options.degeneracy_weight << std::endl;
|
||||
std::cout << "Start : saved MAP-Elites/CEM seeds plus independent random starts"
|
||||
<< std::endl;
|
||||
std::cout << "Coordinates: "
|
||||
@@ -4387,22 +4450,36 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
[&](std::uint64_t sum, int item) {
|
||||
return sum + states[item].scheduler_pulls;
|
||||
});
|
||||
double current_best_severity = std::numeric_limits<double>::infinity();
|
||||
double current_worst_severity = -std::numeric_limits<double>::infinity();
|
||||
int current_best_defects = std::numeric_limits<int>::max() / 4;
|
||||
for (int item : active_topologies) {
|
||||
if (states[item].has_state) {
|
||||
const double severity = topology_scheduler_severity(states[item].best);
|
||||
current_best_severity = std::min(current_best_severity, severity);
|
||||
current_worst_severity = std::max(current_worst_severity, severity);
|
||||
current_best_defects = std::min(
|
||||
current_best_defects,
|
||||
global_defects(states[item].best));
|
||||
}
|
||||
}
|
||||
if (current_best_defects >= std::numeric_limits<int>::max() / 8) {
|
||||
if (!std::isfinite(current_best_severity)) {
|
||||
current_best_severity = 0.0;
|
||||
current_worst_severity = 0.0;
|
||||
current_best_defects = 0;
|
||||
}
|
||||
const double selection_score = topology_bandit_score(
|
||||
state,
|
||||
total_scheduler_pulls,
|
||||
static_cast<std::uint64_t>(completed_rounds + 1),
|
||||
current_best_defects);
|
||||
current_best_severity,
|
||||
current_worst_severity,
|
||||
current_best_defects,
|
||||
options.prioritize_worst);
|
||||
const double selection_worstness = topology_scheduler_worstness(
|
||||
state,
|
||||
current_best_severity,
|
||||
current_worst_severity);
|
||||
const int round_seed = static_cast<int>(
|
||||
1 + (static_cast<std::uint64_t>(static_cast<std::uint32_t>(options.seed)) +
|
||||
static_cast<std::uint64_t>(state.visits + 1) * 15485863ULL +
|
||||
@@ -4476,6 +4553,7 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
<< szilassi::checkpoint::unix_time_ns_now() << "\t"
|
||||
<< phase << "\t" << topology << "\t" << (depth ? 1 : 0) << "\t"
|
||||
<< std::setprecision(17) << selection_score << "\t"
|
||||
<< selection_worstness << "\t"
|
||||
<< (had_before ? before.crossings : -1) << "\t"
|
||||
<< (had_before ? before.intersections : -1) << "\t"
|
||||
<< (state.has_state ? state.best.crossings : -1) << "\t"
|
||||
@@ -4551,13 +4629,22 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
[&](std::uint64_t sum, int topology) {
|
||||
return sum + states[topology].scheduler_pulls;
|
||||
});
|
||||
double best_severity = std::numeric_limits<double>::infinity();
|
||||
double worst_severity = -std::numeric_limits<double>::infinity();
|
||||
int best_defects = std::numeric_limits<int>::max() / 4;
|
||||
for (int topology : active_topologies) {
|
||||
if (states[topology].has_state) {
|
||||
best_defects = std::min(best_defects, global_defects(states[topology].best));
|
||||
const double severity = topology_scheduler_severity(states[topology].best);
|
||||
best_severity = std::min(best_severity, severity);
|
||||
worst_severity = std::max(worst_severity, severity);
|
||||
best_defects = std::min(
|
||||
best_defects,
|
||||
global_defects(states[topology].best));
|
||||
}
|
||||
}
|
||||
if (best_defects >= std::numeric_limits<int>::max() / 8) {
|
||||
if (!std::isfinite(best_severity)) {
|
||||
best_severity = 0.0;
|
||||
worst_severity = 0.0;
|
||||
best_defects = 0;
|
||||
}
|
||||
std::unordered_map<int, double> bandit_scores;
|
||||
@@ -4566,7 +4653,10 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
states[topology],
|
||||
total_scheduler_pulls,
|
||||
static_cast<std::uint64_t>(completed_rounds + 1),
|
||||
best_defects);
|
||||
best_severity,
|
||||
worst_severity,
|
||||
best_defects,
|
||||
options.prioritize_worst);
|
||||
}
|
||||
std::sort(ranked.begin(), ranked.end(), [&](int a, int b) {
|
||||
if (bandit_scores[a] != bandit_scores[b]) {
|
||||
@@ -4575,9 +4665,16 @@ int global_search_all(const LocalRepairOptions& options) {
|
||||
if (states[a].has_state != states[b].has_state) {
|
||||
return states[a].has_state;
|
||||
}
|
||||
return states[a].has_state
|
||||
? better_global_metrics(states[a].best, states[b].best)
|
||||
: a < b;
|
||||
if (!states[a].has_state) {
|
||||
return a < b;
|
||||
}
|
||||
if (better_global_metrics(states[a].best, states[b].best)) {
|
||||
return true;
|
||||
}
|
||||
if (better_global_metrics(states[b].best, states[a].best)) {
|
||||
return false;
|
||||
}
|
||||
return a < b;
|
||||
});
|
||||
|
||||
const bool exploration_cycle = cycle % 5 == 4;
|
||||
@@ -4885,6 +4982,8 @@ int main(int argc, char* argv[]) {
|
||||
} else if (arg == "--degeneracy-weight" && i + 1 < argc) {
|
||||
repair_options.degeneracy_weight = std::clamp(
|
||||
std::atof(argv[++i]), 0.0, 1.0);
|
||||
} else if (arg == "--prioritize-worst") {
|
||||
repair_options.prioritize_worst = true;
|
||||
} else if (arg == "--restarts" && i + 1 < argc) {
|
||||
repair_options.restarts = std::atoi(argv[++i]);
|
||||
} else if (arg == "--stagnation" && i + 1 < argc) {
|
||||
|
||||
Reference in New Issue
Block a user