This commit is contained in:
Efim Beshmenev
2026-07-10 22:26:37 +03:00
parent 7f9dc067a1
commit 8614dfe22a
3757 changed files with 95267 additions and 663 deletions
File diff suppressed because it is too large Load Diff
+203
View File
@@ -0,0 +1,203 @@
#pragma once
#include <cstdint>
#include <filesystem>
#include <map>
#include <optional>
#include <string>
#include <vector>
namespace szilassi::checkpoint {
// Checkpoints are append-only generations. A generation is a single,
// self-contained binary file; there is no separately updated metadata or OBJ
// that could get out of sync after a power failure.
constexpr std::uint32_t kGlobalCheckpointFormatVersion = 2;
constexpr const char* kGlobalCheckpointExtension = ".szcp";
enum class VerificationPrecision : std::uint32_t {
Unverified = 0,
Fp32 = 1,
Double = 2,
DoubleDouble = 3,
};
enum class CheckpointReason : std::uint32_t {
Periodic = 0,
Improvement = 1,
Stop = 2,
Final = 3,
Imported = 4,
};
enum CheckpointFlags : std::uint32_t {
CheckpointFlagNone = 0,
CheckpointFlagCanonical = 1u << 0,
CheckpointFlagDdVerified = 1u << 1,
CheckpointFlagFound = 1u << 2,
};
struct RunIdentity {
// run_id is a random UUID and is the merge namespace. A fresh run_id must
// be created for every process invocation, including after a crash.
std::string run_id;
// node_id is diagnostic only (normally the computer name). Correctness
// and merge conflict avoidance do not rely on it being globally unique.
std::string node_id;
};
struct GlobalCheckpoint {
std::string run_id;
std::string node_id;
std::string producer_id;
std::string device_id;
std::uint64_t sequence = 0;
std::int64_t created_unix_ns = 0;
std::int32_t topology = -1;
std::int32_t topology_first = 0;
std::int32_t topology_last = 58;
std::uint32_t objective_version = 0;
std::uint64_t topology_fingerprint = 0;
std::uint64_t base_seed = 0;
// Work identifiers are local to run_id and topology. Persist only the
// fully committed frontier; in-flight work may safely be repeated.
std::uint64_t next_work_unit = 0;
std::uint64_t completed_work_units = 0;
std::uint64_t completed_trials = 0;
std::uint64_t completed_iterations = 0;
std::uint64_t visits = 0;
std::int32_t crossings = 0;
std::int32_t intersections = 0;
double crossing_loss = 0.0;
double degeneracy_penalty = 0.0;
double energy = 0.0;
VerificationPrecision verification = VerificationPrecision::Unverified;
CheckpointReason reason = CheckpointReason::Periodic;
std::uint32_t flags = CheckpointFlagNone;
// CUDA search coordinates are stored as raw IEEE-754 binary32 values in
// the file. DD verification should lift these exact values, not a rounded
// textual representation.
std::vector<float> plane_coefficients;
};
struct CheckpointRecord {
std::filesystem::path path;
GlobalCheckpoint checkpoint;
std::uint32_t crc32 = 0;
};
struct CheckpointIssue {
std::filesystem::path path;
std::string message;
};
struct CheckpointConflict {
std::string run_id;
std::int32_t topology = -1;
std::uint64_t sequence = 0;
std::vector<std::filesystem::path> paths;
};
struct CommitResult {
bool success = false;
bool already_existed = false;
std::filesystem::path path;
std::uint32_t crc32 = 0;
std::string error;
explicit operator bool() const noexcept { return success; }
};
struct ReadResult {
std::optional<CheckpointRecord> record;
std::string error;
explicit operator bool() const noexcept { return record.has_value(); }
};
struct LoadLatestResult {
std::optional<CheckpointRecord> record;
// Corrupt/truncated newer generations and conflicting sequences are
// reported here. record, when present, is the newest older valid fallback.
std::vector<CheckpointIssue> rejected;
explicit operator bool() const noexcept { return record.has_value(); }
};
struct CheckpointScan {
std::vector<CheckpointRecord> valid;
std::vector<CheckpointIssue> rejected;
// Same (run_id, topology, sequence) with different CRCs means a run_id was
// cloned and advanced independently. Such a sequence is never selected.
std::vector<CheckpointConflict> conflicts;
};
struct RunTopologyKey {
std::string run_id;
std::int32_t topology = -1;
bool operator<(const RunTopologyKey& other) const noexcept;
};
using LatestCheckpointMap = std::map<RunTopologyKey, CheckpointRecord>;
std::string generate_run_id();
std::string default_node_id();
RunIdentity make_run_identity(const std::string& node_id_override = {});
std::int64_t unix_time_ns_now();
bool validate_checkpoint(const GlobalCheckpoint& checkpoint, std::string* error = nullptr);
// Binary format (all integer and IEEE-754 fields are little-endian):
// 32-byte header: magic[8], version:u32, header_size:u32,
// payload_size:u64, payload_crc32:u32, reserved:u32
// payload: length-prefixed UTF-8 identifiers, progress, metrics, flags,
// coefficient_count:u32, coefficient bits.
// CRC-32/IEEE covers the complete payload.
std::vector<std::uint8_t> serialize_checkpoint(
const GlobalCheckpoint& checkpoint,
std::uint32_t* payload_crc32 = nullptr,
std::string* error = nullptr);
ReadResult read_checkpoint(const std::filesystem::path& path);
std::filesystem::path checkpoint_directory(
const std::filesystem::path& global_root,
const std::string& run_id,
std::int32_t topology);
// Writes a new immutable generation under:
// <root>/runs/<run-id>/topology_NNN/checkpoints/
// checkpoint_<20-digit-sequence>_<crc32>.szcp
// The temporary file is written in the same directory, flushed durably, and
// atomically published. Existing different contents are never overwritten.
CommitResult commit_checkpoint(
const std::filesystem::path& global_root,
GlobalCheckpoint checkpoint);
// Reads all generations in one checkpoint directory. Corrupt latest files or
// divergent same-sequence files are skipped, so the result automatically falls
// back to the preceding valid generation.
LoadLatestResult load_latest_with_fallback(
const std::filesystem::path& directory,
const std::string& expected_run_id = {},
std::int32_t expected_topology = -1);
// Scans only the merge namespace <root>/runs. Temporary files, root-level
// leaderboard/log files, and legacy resume.* files are deliberately ignored.
// Consequently merging two result trees is a union/copy of runs/* followed by
// this scan; derived reports can then be rebuilt.
CheckpointScan scan_checkpoints(const std::filesystem::path& global_root);
// Selects the newest non-conflicting valid generation for every
// (run_id, topology). Aggregate counters by summing these per-run records;
// never carry an already aggregated total into a new run checkpoint.
LatestCheckpointMap select_latest_per_run_topology(const CheckpointScan& scan);
} // namespace szilassi::checkpoint
File diff suppressed because it is too large Load Diff
+152
View File
@@ -0,0 +1,152 @@
#pragma once
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
namespace cuda_search {
constexpr int kPlaneCount = 12;
constexpr int kPlaneComponents = 3;
constexpr int kPlaneValueCount = kPlaneCount * kPlaneComponents;
constexpr int kVertexCount = 44;
constexpr int kPolygonCount = 12;
constexpr int kPolygonVertexCount = 11;
constexpr int kEdgeCount = 66;
constexpr int kNonincidentEdgesPerPolygon = 44;
enum AmbiguityFlag : std::uint32_t {
kAmbiguityNone = 0,
kAmbiguityPlaneTriple = 1u << 0,
kAmbiguitySegment = 1u << 1,
kAmbiguityEdgePlane = 1u << 2,
kAmbiguityPolygonBoundary = 1u << 3,
kAmbiguityDegenerateGeometry = 1u << 4,
kAmbiguityInvalidState = 1u << 31,
};
// Fixed combinatorial description used by the global search. Indices are
// zero-based. vertex_planes[v] contains the three planes whose intersection
// produces vertex v.
struct Topology {
std::array<std::array<std::uint8_t, 3>, kVertexCount> vertex_planes{};
std::array<std::array<std::uint8_t, kPolygonVertexCount>, kPolygonCount> polygons{};
std::array<std::array<std::uint8_t, 2>, kEdgeCount> edges{};
};
// Plane i is encoded by values[3*i..3*i+2] = normal * distance, matching the
// existing VectorXd representation. CUDA keeps these values in FP32.
struct PlaneState {
std::array<float, kPlaneValueCount> values{};
};
struct SearchConfig {
int device_index = 0;
// Zero selects the occupancy-derived recommendation for the device.
int chain_count = 0;
int iterations_per_kernel = 16;
int iterations_per_batch = 64;
int shortlist_size = 128;
std::uint64_t seed = 30000157;
float initial_step = 0.05f;
float minimum_step = 1.0e-6f;
float cooling = 0.9995f;
float initial_temperature = 0.02f;
float minimum_temperature = 8.0e-4f;
float jump_chance = 0.08f;
float initial_state_jitter = 0.02f;
float degeneracy_weight = 0.02f;
int stagnation_iterations = 2000;
};
// Per-batch controls which do not change the persistent session layout.
// A deterministic fraction of chains can be restarted as fresh independent
// trials. The caller remains responsible for retaining the global best.
struct BatchRunConfig {
int fresh_numerator = 0;
int fresh_denominator = 1;
float step_scale = 1.0f;
};
struct Candidate {
PlaneState state;
int crossings = 0;
int intersections = 0;
float crossing_loss = 0.0f;
float geometry_penalty = 0.0f;
float degeneracy_penalty = 0.0f;
float energy = 0.0f;
std::uint32_t ambiguity_flags = kAmbiguityNone;
std::uint64_t chain_id = 0;
std::uint64_t iterations = 0;
};
struct BackendInfo {
bool available = false;
int device_count = 0;
int selected_device = -1;
int multiprocessor_count = 0;
int active_blocks_per_multiprocessor = 0;
int recommended_chain_count = 0;
std::string device_name;
std::string error;
};
struct BatchResult {
bool success = false;
std::string error;
std::string device_name;
int device_index = -1;
int stream_priority = 0;
double kernel_milliseconds = 0.0;
double transfer_milliseconds = 0.0;
double wall_milliseconds = 0.0;
std::uint64_t evaluated_states = 0;
std::vector<Candidate> shortlist;
};
BackendInfo query_backend(int device_index = 0);
// A session owns one topology and persistent independent search chains. run()
// launches short kernels and leaves the chain states resident on the device,
// so repeated calls continue the same search.
class BatchSession {
public:
BatchSession();
~BatchSession();
BatchSession(BatchSession&& other) noexcept;
BatchSession& operator=(BatchSession&& other) noexcept;
BatchSession(const BatchSession&) = delete;
BatchSession& operator=(const BatchSession&) = delete;
bool initialize(
const Topology& topology,
const SearchConfig& config,
const std::vector<PlaneState>& initial_states,
std::string& error);
BatchResult run(const BatchRunConfig& config = {});
void reset();
bool initialized() const noexcept;
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
// Convenience one-shot wrapper. Use BatchSession directly when search must be
// continued over many GUI/background ticks.
BatchResult run_batch(
const Topology& topology,
const SearchConfig& config,
const std::vector<PlaneState>& initial_states = {});
} // namespace cuda_search
+76
View File
@@ -0,0 +1,76 @@
#include "cuda_search.h"
#include <utility>
// Build this translation unit only in the CPU-only target. CUDA-enabled
// targets compile cuda_search.cu instead; both files intentionally implement
// the same public ABI.
namespace cuda_search {
namespace {
constexpr const char* kUnavailableMessage =
"CUDA search backend is not compiled into this executable.";
} // namespace
struct BatchSession::Impl {
bool is_initialized = false;
};
BackendInfo query_backend(int device_index) {
BackendInfo result;
result.selected_device = device_index;
result.error = kUnavailableMessage;
return result;
}
BatchSession::BatchSession() : impl_(std::make_unique<Impl>()) {}
BatchSession::~BatchSession() = default;
BatchSession::BatchSession(BatchSession&& other) noexcept = default;
BatchSession& BatchSession::operator=(BatchSession&& other) noexcept = default;
bool BatchSession::initialize(
const Topology&,
const SearchConfig&,
const std::vector<PlaneState>&,
std::string& error) {
if (!impl_) {
impl_ = std::make_unique<Impl>();
}
impl_->is_initialized = false;
error = kUnavailableMessage;
return false;
}
BatchResult BatchSession::run(const BatchRunConfig&) {
BatchResult result;
result.error = kUnavailableMessage;
return result;
}
void BatchSession::reset() {
if (impl_) {
impl_->is_initialized = false;
}
}
bool BatchSession::initialized() const noexcept {
return impl_ != nullptr && impl_->is_initialized;
}
BatchResult run_batch(
const Topology&,
const SearchConfig& config,
const std::vector<PlaneState>&) {
BatchResult result;
result.device_index = config.device_index;
result.error = kUnavailableMessage;
return result;
}
} // namespace cuda_search