// engram_server: the x86host Engram table server (lane O1, DSV41-OFFLOAD). // // Loads the Engram tables of the checkpoint's shards (model-00047/48-of-00048.safetensors: layer 1 and layer 14) into // ONE anonymous resident copy each: the whole shard file is read with O_DIRECT (no page cache) straight into an // anonymous mapping advised for transparent huge pages, while a second thread hashes it in order; the shard must match // its sha256 in the repo's manifest.json or the server refuses to start. Nothing is pinned or registered except the // transport's bounded per-connection pools. The few hundred MB of non-Engram tensors at the end of each shard are hashed // and then released. // // Serves "engram-v1" (engram_proto.h) over ofl (TCP + RDMA) with one listener per direct link (10.202.28.1 for Spark A / // rank 0, 10.202.29.1 for Spark B / rank 1). LOOKUP gathers rows in request order into the registered response buffer // (weights block, then scales block = the engine's staging layout), in parallel chunks that go out on the wire as they // finish (ofl_req_ready). Row id kZeroRow reads as zeros, exactly like the engine's disk reader for its -1 padding. // // engram_server --data /data/dsv41-offload/engram --manifest ~/dsv41-offload/o1/manifest.json // --listen 10.202.28.1 --listen 10.202.29.1 [--port 18610] [--backends tcp,rdma] [--threads 8] // [--budget-gib 215] [--wait-marker ENGRAM_COPY_DONE] [--max-rows 98304] [--stats FILE] [--no-verify] #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../transport/ofl.h" #include "../engram_proto.h" using namespace engram; namespace { volatile sig_atomic_t g_stop = 0; void on_sig(int) { g_stop = 1; } int64_t now_ns() { timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000LL + ts.tv_nsec; } void logf(const char* f, ...) __attribute__((format(printf, 1, 2))); void logf(const char* f, ...) { char tb[32]; time_t t = time(nullptr); strftime(tb, sizeof(tb), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); va_list ap; va_start(ap, f); fprintf(stderr, "%s engram_server: ", tb); vfprintf(stderr, f, ap); fprintf(stderr, "\n"); va_end(ap); } [[noreturn]] void die(const char* f, ...) __attribute__((format(printf, 1, 2))); void die(const char* f, ...) { va_list ap; va_start(ap, f); fprintf(stderr, "engram_server: FATAL: "); vfprintf(stderr, f, ap); fprintf(stderr, "\n"); va_end(ap); exit(2); } uint64_t meminfo_kb(const char* key) { FILE* f = fopen("/proc/meminfo", "r"); if (!f) return 0; char line[256]; uint64_t v = 0; const size_t kl = strlen(key); while (fgets(line, sizeof(line), f)) if (!strncmp(line, key, kl) && line[kl] == ':') { v = strtoull(line + kl + 1, nullptr, 10); break; } fclose(f); return v; } uint64_t self_kb(const char* key) { // /proc/self/status (VmRSS, VmHWM, ...) FILE* f = fopen("/proc/self/status", "r"); if (!f) return 0; char line[256]; uint64_t v = 0; const size_t kl = strlen(key); while (fgets(line, sizeof(line), f)) if (!strncmp(line, key, kl) && line[kl] == ':') { v = strtoull(line + kl + 1, nullptr, 10); break; } fclose(f); return v; } // ---- whole-shard hashing: OpenSSL libcrypto when present (SHA-NI), else the portable implementation ------------- struct Hasher { using NewFn = void* (*)(); using FreeFn = void (*)(void*); using MdFn = const void* (*)(); using InitFn = int (*)(void*, const void*, void*); using UpdFn = int (*)(void*, const void*, size_t); using FinFn = int (*)(void*, unsigned char*, unsigned int*); NewFn mk = nullptr; FreeFn fr = nullptr; MdFn md = nullptr; InitFn init = nullptr; UpdFn upd = nullptr; FinFn fin = nullptr; bool ok = false; Hasher() { void* h = dlopen("libcrypto.so.3", RTLD_NOW | RTLD_LOCAL); if (!h) return; mk = (NewFn)dlsym(h, "EVP_MD_CTX_new"); fr = (FreeFn)dlsym(h, "EVP_MD_CTX_free"); md = (MdFn)dlsym(h, "EVP_sha256"); init = (InitFn)dlsym(h, "EVP_DigestInit_ex"); upd = (UpdFn)dlsym(h, "EVP_DigestUpdate"); fin = (FinFn)dlsym(h, "EVP_DigestFinal_ex"); ok = mk && fr && md && init && upd && fin; if (ok) { // self-test against the portable implementation uint8_t a[32], b[32]; const char* t = "engram_server sha256 self-test"; Sha256 s; s.update(t, strlen(t)); s.final(a); void* c = mk(); unsigned n = 0; ok = c && init(c, md(), nullptr) == 1 && upd(c, t, strlen(t)) == 1 && fin(c, b, &n) == 1 && n == 32 && !memcmp(a, b, 32); if (c) fr(c); } } }; struct Stream { // one running whole-file hash const Hasher& H; void* ctx = nullptr; Sha256 portable; explicit Stream(const Hasher& h) : H(h) { if (H.ok) { ctx = H.mk(); H.init(ctx, H.md(), nullptr); } } ~Stream() { if (ctx) H.fr(ctx); } void update(const void* p, size_t n) { if (ctx) H.upd(ctx, p, n); else portable.update(p, n); } void final(uint8_t out[32]) { if (ctx) { unsigned n = 0; H.fin(ctx, out, &n); } else portable.final(out); } }; // ---- a loaded table --------------------------------------------------------------------------------------------- struct Table { TableDesc d; uint8_t identity[32]; std::string path; uint8_t* base = nullptr; // anonymous mapping holding file bytes [0, file size) size_t map_bytes = 0; const uint8_t* w = nullptr; // row 0 weights const uint8_t* s = nullptr; // row 0 scales double load_s = 0, hash_s = 0; std::string sha_actual; }; constexpr size_t kChunk = 64ull << 20; // O_DIRECT read unit constexpr size_t kHuge = 2ull << 20; void load_table(Table& t, const Hasher& H, bool verify, int readers) { const int64_t t0 = now_ns(); const uint64_t size = t.d.shard_size; t.map_bytes = ((size + kHuge - 1) / kHuge) * kHuge + kHuge; void* m = mmap(nullptr, t.map_bytes + kHuge, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); if (m == MAP_FAILED) die("mmap %zu bytes for %s: %s", t.map_bytes, t.d.shard.c_str(), strerror(errno)); uint8_t* aligned = reinterpret_cast(((uintptr_t)m + kHuge - 1) & ~(uintptr_t)(kHuge - 1)); t.base = aligned; if (madvise(t.base, t.map_bytes, MADV_HUGEPAGE) != 0) logf("madvise(MADV_HUGEPAGE) failed: %s (small pages)", strerror(errno)); const int fd = ::open(t.path.c_str(), O_RDONLY | O_CLOEXEC | O_DIRECT); if (fd < 0) die("open %s O_DIRECT: %s", t.path.c_str(), strerror(errno)); const size_t nchunks = (size + kChunk - 1) / kChunk; std::unique_ptr[]> ready(new std::atomic[nchunks]); for (size_t i = 0; i < nchunks; i++) ready[i].store(0); std::atomic next{0}; std::atomic err{0}; std::vector th; for (int r = 0; r < readers; r++) th.emplace_back([&] { for (size_t c; (c = next.fetch_add(1)) < nchunks && !err.load() && !g_stop;) { const uint64_t off = (uint64_t)c * kChunk; size_t want = (size_t)std::min(kChunk, size - off); want = (want + 4095) & ~size_t(4095); // O_DIRECT length; the mapping has room past EOF size_t got = 0; while (got < want) { const ssize_t k = pread(fd, t.base + off + got, want - got, (off_t)(off + got)); if (k < 0 && errno == EINTR) continue; if (k < 0) { logf("pread %s at %llu: %s", t.path.c_str(), (unsigned long long)(off + got), strerror(errno)); err = 1; break; } if (k == 0) break; // EOF (last chunk) got += (size_t)k; } if (!err && off + got < std::min(off + kChunk, size)) { logf("short read of %s at chunk %zu", t.path.c_str(), c); err = 1; } ready[c].store(1, std::memory_order_release); } }); uint8_t digest[32] = {0}; int64_t hash_ns = 0; if (verify) { Stream st(H); for (size_t c = 0; c < nchunks && !err.load() && !g_stop; c++) { while (!ready[c].load(std::memory_order_acquire) && !err.load() && !g_stop) usleep(200); if (err.load() || g_stop) break; const int64_t h0 = now_ns(); const uint64_t off = (uint64_t)c * kChunk; st.update(t.base + off, (size_t)std::min(kChunk, size - off)); hash_ns += now_ns() - h0; } st.final(digest); } for (auto& x : th) x.join(); ::close(fd); if (g_stop) die("stopped while loading %s", t.d.shard.c_str()); if (err.load()) die("reading %s failed", t.path.c_str()); t.hash_s = hash_ns / 1e9; if (verify) { t.sha_actual = hex(digest, 32); if (t.sha_actual != t.d.shard_sha256) die("%s: sha256 %s, the manifest says %s: refusing to serve it", t.path.c_str(), t.sha_actual.c_str(), t.d.shard_sha256.c_str()); } // keep the Engram tensors, release the rest of the shard (header pages stay: they share a page with the weights) const uint64_t w_end = t.d.weight.abs_offset + t.d.weight.nbytes, s_end = t.d.scale.abs_offset + t.d.scale.nbytes; if (w_end > size || s_end > size) die("%s: Engram tensors run past the end of the file", t.path.c_str()); const uint64_t keep_end = std::max(w_end, s_end); const uintptr_t rel = ((uintptr_t)(t.base + keep_end) + 4095) & ~(uintptr_t)4095; const uintptr_t end = (uintptr_t)(t.base + t.map_bytes); if (end > rel) madvise(reinterpret_cast(rel), end - rel, MADV_DONTNEED); t.w = t.base + t.d.weight.abs_offset; t.s = t.base + t.d.scale.abs_offset; t.load_s = (now_ns() - t0) / 1e9; // the copy we read is resident now; drop the shard's (clean) page cache so the bytes are not held twice const int pfd = ::open(t.path.c_str(), O_RDONLY | O_CLOEXEC); if (pfd >= 0) { posix_fadvise(pfd, 0, 0, POSIX_FADV_DONTNEED); ::close(pfd); } } // ---- gather pool ------------------------------------------------------------------------------------------------ struct Job { const uint8_t* w = nullptr; // range row 0 const uint8_t* s = nullptr; const uint32_t* ids = nullptr; uint32_t n = 0; uint8_t* out = nullptr; // weights [n*256] then scales [n*8] ofl_req* req = nullptr; uint32_t chunk = 2048; uint32_t nchunks = 0; std::atomic next{0}, done{0}; std::atomic active{0}; // pool workers holding a pointer to this (stack) job; run() waits for 0 std::atomic zero_rows{0}; }; inline void gather_rows(Job& j, uint32_t i0, uint32_t i1) { uint8_t* ow = j.out; uint8_t* os = j.out + (size_t)j.n * kRowBytes; constexpr uint32_t PF = 12; // rows prefetched ahead uint64_t zeros = 0; for (uint32_t i = i0; i < std::min(i1, i0 + PF); i++) { const uint32_t id = j.ids[i]; if (id != kZeroRow) { const uint8_t* p = j.w + (size_t)id * kRowBytes; __builtin_prefetch(p); __builtin_prefetch(p + 64); __builtin_prefetch(p + 128); __builtin_prefetch(p + 192); __builtin_prefetch(j.s + (size_t)id * kScaleBytes); } } for (uint32_t i = i0; i < i1; i++) { if (i + PF < i1) { const uint32_t nid = j.ids[i + PF]; if (nid != kZeroRow) { const uint8_t* p = j.w + (size_t)nid * kRowBytes; __builtin_prefetch(p); __builtin_prefetch(p + 64); __builtin_prefetch(p + 128); __builtin_prefetch(p + 192); __builtin_prefetch(j.s + (size_t)nid * kScaleBytes); } } const uint32_t id = j.ids[i]; if (id == kZeroRow) { memset(ow + (size_t)i * kRowBytes, 0, kRowBytes); memset(os + (size_t)i * kScaleBytes, 0, kScaleBytes); zeros++; } else { memcpy(ow + (size_t)i * kRowBytes, j.w + (size_t)id * kRowBytes, kRowBytes); memcpy(os + (size_t)i * kScaleBytes, j.s + (size_t)id * kScaleBytes, kScaleBytes); } } if (zeros) j.zero_rows.fetch_add(zeros, std::memory_order_relaxed); } class Pool { public: explicit Pool(int n, int64_t spin_ns) : spin_ns_(spin_ns) { for (int i = 0; i < n; i++) th_.emplace_back([this] { loop(); }); } ~Pool() { { std::lock_guard g(mu_); stop_.store(true); } cv_.notify_all(); for (auto& t : th_) t.join(); } // Run j with the pool's help; the caller works too. Returns when every chunk is gathered and marked ready and no // worker holds a pointer to j any more (j lives on the caller's stack). void run(Job& j) { { std::lock_guard g(mu_); jobs_.push_back(&j); gen_.fetch_add(1, std::memory_order_release); } cv_.notify_all(); work(j); while (j.done.load(std::memory_order_acquire) < j.nchunks) cpu_relax(); { std::lock_guard g(mu_); // after this no worker can pick j ... jobs_.erase(std::remove(jobs_.begin(), jobs_.end(), &j), jobs_.end()); } while (j.active.load(std::memory_order_acquire) != 0) cpu_relax(); // ... and every one that did has let go } static void work(Job& j) { for (uint32_t c; (c = j.next.fetch_add(1, std::memory_order_relaxed)) < j.nchunks;) { const uint32_t i0 = c * j.chunk, i1 = std::min(j.n, i0 + j.chunk); gather_rows(j, i0, i1); if (j.req) { ofl_req_ready(j.req, i0 * kRowBytes, (i1 - i0) * kRowBytes); ofl_req_ready(j.req, j.n * kRowBytes + i0 * kScaleBytes, (i1 - i0) * kScaleBytes); } j.done.fetch_add(1, std::memory_order_release); } } private: static void cpu_relax() { #if defined(__x86_64__) __builtin_ia32_pause(); #elif defined(__aarch64__) asm volatile("isb" ::: "memory"); #endif } // A job with unclaimed chunks, pinned (active + 1, under mu_, so run() cannot have erased it yet); release() after. Job* pick() { std::lock_guard g(mu_); for (Job* j : jobs_) if (j->next.load(std::memory_order_relaxed) < j->nchunks) { j->active.fetch_add(1, std::memory_order_acq_rel); return j; } return nullptr; } static void release(Job* j) { j->active.fetch_sub(1, std::memory_order_release); } // the worker's last touch of j // Workers spin (lock-free, on gen_) for spin_ns_ after the last job they saw, then sleep on the condition variable // until a job is pushed. Only a new job restarts the spin window (a timed-out wait does not). void loop() { int64_t last = now_ns(); uint64_t seen = gen_.load(std::memory_order_acquire); for (;;) { if (stop_.load(std::memory_order_relaxed)) return; const uint64_t g = gen_.load(std::memory_order_acquire); if (g != seen) { // jobs were pushed: help with every one that still has chunks seen = g; while (Job* j = pick()) { work(*j); release(j); } last = now_ns(); continue; } if (now_ns() - last < spin_ns_) { for (int k = 0; k < 64; k++) cpu_relax(); continue; } std::unique_lock l(mu_); cv_.wait_for(l, std::chrono::milliseconds(100), [&] { return stop_.load() || gen_.load(std::memory_order_acquire) != seen; }); } } std::vector th_; std::mutex mu_; std::condition_variable cv_; std::vector jobs_; std::atomic gen_{0}; std::atomic stop_{false}; int64_t spin_ns_; }; // ---- service state ---------------------------------------------------------------------------------------------- struct Handle { int table; uint64_t row_start, num_rows; }; struct Hist { // log2 histogram of handler time, ns std::atomic b[32]; Hist() { for (auto& x : b) x.store(0); } void add(int64_t ns) { int k = 0; while (k < 31 && (1LL << (k + 1)) <= ns) k++; b[k].fetch_add(1, std::memory_order_relaxed); } }; struct Service { std::vector> tables; std::mutex hmu; std::vector handles; std::unique_ptr pool; uint32_t inline_rows = 1024; uint32_t chunk_rows = 2048; std::atomic ready{false}; std::atomic opens{0}, lookups{0}, rows{0}, zero_rows{0}, bytes{0}, refused{0}; std::atomic lookup_ns{0}; Hist hist; std::string started; }; Service g_svc; int32_t handle_open(ofl_req* r) { uint32_t n = 0; const void* p = ofl_req_payload(r, &n); if (n != sizeof(OpenReq)) return kErrBadRequest; OpenReq q; memcpy(&q, p, sizeof(q)); q.client[sizeof(q.client) - 1] = 0; if (q.version != kProtoVersion) return kErrBadRequest; int ti = -1; for (size_t i = 0; i < g_svc.tables.size(); i++) if (!memcmp(g_svc.tables[i]->identity, q.identity, 32)) ti = (int)i; if (ti < 0) { g_svc.refused++; logf("OPEN refused for '%s' (conn %llu): identity %s matches no loaded table", q.client, (unsigned long long)ofl_req_conn_id(r), hex(q.identity, 32).c_str()); return kErrIdentity; } const Table& t = *g_svc.tables[ti]; if ((int)q.layer_id != t.d.layer_id || q.row_bytes != kRowBytes || q.scale_bytes != kScaleBytes || q.num_rows == 0 || q.row_start > t.d.rows() || q.num_rows > t.d.rows() - q.row_start || q.num_rows >= kZeroRow) { g_svc.refused++; logf("OPEN refused for '%s': layer %u rows [%llu, +%llu) row %u/%u B vs table layer %d of %llu rows", q.client, q.layer_id, (unsigned long long)q.row_start, (unsigned long long)q.num_rows, q.row_bytes, q.scale_bytes, t.d.layer_id, (unsigned long long)t.d.rows()); return kErrRange; } uint32_t h; { std::lock_guard g(g_svc.hmu); h = (uint32_t)g_svc.handles.size(); for (uint32_t i = 0; i < g_svc.handles.size(); i++) if (g_svc.handles[i].table == ti && g_svc.handles[i].row_start == q.row_start && g_svc.handles[i].num_rows == q.num_rows) h = i; if (h == g_svc.handles.size()) g_svc.handles.push_back(Handle{ti, q.row_start, q.num_rows}); } uint32_t cap = 0; void* out = ofl_req_resp_buf(r, &cap); if (cap < sizeof(OpenResp)) return kErrTooMany; OpenResp a{}; a.version = kProtoVersion; a.handle = h; a.table_rows = t.d.rows(); memcpy(a.identity, t.identity, 32); snprintf(a.desc, sizeof(a.desc), "%s layer %d rows [%llu, %llu) of %llu", t.d.shard.c_str(), t.d.layer_id, (unsigned long long)q.row_start, (unsigned long long)(q.row_start + q.num_rows), (unsigned long long)t.d.rows()); memcpy(out, &a, sizeof(a)); ofl_req_set_len(r, sizeof(a)); g_svc.opens++; logf("OPEN '%s' (conn %llu, %s): handle %u = %s", q.client, (unsigned long long)ofl_req_conn_id(r), ofl_req_backend(r) == OFL_BACKEND_RDMA ? "rdma" : "tcp", h, a.desc); return 0; } int32_t handle_lookup(ofl_req* r) { const int64_t t0 = now_ns(); uint32_t n = 0; const uint8_t* p = static_cast(ofl_req_payload(r, &n)); if (n < sizeof(LookupHdr)) return kErrBadRequest; LookupHdr q; memcpy(&q, p, sizeof(q)); if ((uint64_t)n != sizeof(LookupHdr) + 4ull * q.n) return kErrBadRequest; Handle h; { std::lock_guard g(g_svc.hmu); if (q.handle >= g_svc.handles.size()) return kErrHandle; h = g_svc.handles[q.handle]; } const Table& t = *g_svc.tables[h.table]; if (memcmp(t.identity, q.identity, 32)) { g_svc.refused++; return kErrIdentity; } uint32_t cap = 0; uint8_t* out = static_cast(ofl_req_resp_buf(r, &cap)); const uint64_t need = (uint64_t)q.n * (kRowBytes + kScaleBytes); if (need > cap) return kErrTooMany; const uint32_t* ids = reinterpret_cast(p + sizeof(LookupHdr)); // 4-byte aligned: 64+16k+40 for (uint32_t i = 0; i < q.n; i++) if (ids[i] != kZeroRow && ids[i] >= h.num_rows) { g_svc.refused++; return kErrRowId; } Job j; j.w = t.w + h.row_start * kRowBytes; j.s = t.s + h.row_start * kScaleBytes; j.ids = ids; j.n = q.n; j.out = out; if (q.n <= g_svc.inline_rows || !g_svc.pool) { gather_rows(j, 0, q.n); // decode-size: one pass in this thread; the transport sends it after we return } else { j.req = r; j.chunk = g_svc.chunk_rows; j.nchunks = (q.n + j.chunk - 1) / j.chunk; g_svc.pool->run(j); } ofl_req_set_len(r, (uint32_t)need); const int64_t dt = now_ns() - t0; g_svc.lookups++; g_svc.rows += q.n; g_svc.zero_rows += j.zero_rows.load(); g_svc.bytes += need; g_svc.lookup_ns += (uint64_t)dt; g_svc.hist.add(dt); return 0; } std::string stats_json() { std::string s = "{\"service\":\"engram-v1\",\"started\":\"" + g_svc.started + "\",\"ready\":" + (g_svc.ready.load() ? "true" : "false") + ",\"tables\":["; for (size_t i = 0; i < g_svc.tables.size(); i++) { const Table& t = *g_svc.tables[i]; char b[640]; snprintf(b, sizeof(b), "%s{\"shard\":\"%s\",\"layer\":%d,\"rows\":%llu,\"identity\":\"%s\",\"sha256\":\"%s\",\"verified\":%s," "\"load_s\":%.1f,\"hash_s\":%.1f}", i ? "," : "", t.d.shard.c_str(), t.d.layer_id, (unsigned long long)t.d.rows(), hex(t.identity, 32).c_str(), t.d.shard_sha256.c_str(), t.sha_actual.empty() ? "false" : "true", t.load_s, t.hash_s); s += b; } char b[1024]; snprintf(b, sizeof(b), "],\"opens\":%llu,\"lookups\":%llu,\"rows\":%llu,\"zero_rows\":%llu,\"bytes\":%llu,\"refused\":%llu," "\"lookup_us_mean\":%.1f,\"rss_gib\":%.2f,\"hwm_gib\":%.2f,\"anon_huge_gib\":%.2f,\"mem_available_gib\":%.1f," "\"hist_log2_ns\":[", (unsigned long long)g_svc.opens.load(), (unsigned long long)g_svc.lookups.load(), (unsigned long long)g_svc.rows.load(), (unsigned long long)g_svc.zero_rows.load(), (unsigned long long)g_svc.bytes.load(), (unsigned long long)g_svc.refused.load(), g_svc.lookups.load() ? g_svc.lookup_ns.load() / 1e3 / g_svc.lookups.load() : 0.0, self_kb("VmRSS") / 1048576.0, self_kb("VmHWM") / 1048576.0, meminfo_kb("AnonHugePages") / 1048576.0, meminfo_kb("MemAvailable") / 1048576.0); s += b; for (int k = 0; k < 32; k++) s += (k ? "," : "") + std::to_string(g_svc.hist.b[k].load()); return s + "]}"; } int32_t handler(void*, ofl_req* r) { switch (ofl_req_op(r)) { case kOpOpen: return g_svc.ready.load() ? handle_open(r) : kErrNotReady; case kOpLookup: return g_svc.ready.load() ? handle_lookup(r) : kErrNotReady; case kOpStats: { const std::string s = stats_json(); uint32_t cap = 0; void* out = ofl_req_resp_buf(r, &cap); const uint32_t k = (uint32_t)std::min(s.size(), cap); memcpy(out, s.data(), k); ofl_req_set_len(r, k); return 0; } default: return kErrBadRequest; } } std::vector args_all(int argc, char** argv, const char* name) { std::vector v; for (int i = 1; i + 1 < argc; i++) if (!strcmp(argv[i], name)) v.push_back(argv[i + 1]); return v; } const char* arg(int argc, char** argv, const char* name, const char* def) { for (int i = 1; i + 1 < argc; i++) if (!strcmp(argv[i], name)) return argv[i + 1]; return def; } bool flag(int argc, char** argv, const char* name) { for (int i = 1; i < argc; i++) if (!strcmp(argv[i], name)) return true; return false; } } // namespace int main(int argc, char** argv) { const std::string data = arg(argc, argv, "--data", "/data/dsv41-offload/engram"); const std::string manifest = arg(argc, argv, "--manifest", ""); const std::vector listen = args_all(argc, argv, "--listen"); const uint16_t port = (uint16_t)atoi(arg(argc, argv, "--port", "18610")); const std::string be = arg(argc, argv, "--backends", "tcp,rdma"); const int threads = atoi(arg(argc, argv, "--threads", "8")); const double budget_gib = atof(arg(argc, argv, "--budget-gib", "215")); const double reserve_gib = atof(arg(argc, argv, "--reserve-gib", "48")); // MemAvailable that must remain const std::string marker = arg(argc, argv, "--wait-marker", ""); const uint32_t max_rows = (uint32_t)atol(arg(argc, argv, "--max-rows", "98304")); const std::string stats_path = arg(argc, argv, "--stats", ""); const bool verify = !flag(argc, argv, "--no-verify"); const std::vector only = args_all(argc, argv, "--shard"); // default: every *.safetensors in --data const int readers = atoi(arg(argc, argv, "--readers", "4")); g_svc.inline_rows = (uint32_t)atol(arg(argc, argv, "--inline-rows", "1024")); g_svc.chunk_rows = (uint32_t)atol(arg(argc, argv, "--chunk-rows", "2048")); if (manifest.empty() || listen.empty()) { fprintf(stderr, "usage: engram_server --manifest manifest.json --listen IP [--listen IP] [--data DIR] [--port N] " "[--backends tcp,rdma] [--threads N] [--budget-gib G] [--wait-marker NAME] [--stats FILE]\n"); return 64; } signal(SIGINT, on_sig); signal(SIGTERM, on_sig); signal(SIGPIPE, SIG_IGN); { char tb[32]; time_t t = time(nullptr); strftime(tb, sizeof(tb), "%Y-%m-%dT%H:%M:%SZ", gmtime(&t)); g_svc.started = tb; } if (!marker.empty()) { const std::string mp = data + "/" + marker; struct stat st {}; if (stat(mp.c_str(), &st) != 0) logf("waiting for %s (the copy of the shards)", mp.c_str()); while (stat(mp.c_str(), &st) != 0 && !g_stop) sleep(10); if (g_stop) return 1; } std::vector files = only; if (files.empty()) { DIR* d = opendir(data.c_str()); if (!d) die("cannot open %s: %s", data.c_str(), strerror(errno)); while (dirent* e = readdir(d)) { const std::string n = e->d_name; if (n.size() > 12 && n.compare(n.size() - 12, 12, ".safetensors") == 0) files.push_back(n); } closedir(d); std::sort(files.begin(), files.end()); } if (files.empty()) die("no .safetensors shards in %s", data.c_str()); uint64_t need = 0; for (const auto& f : files) { auto t = std::make_unique(); t->path = f.find('/') == std::string::npos ? data + "/" + f : f; std::string msg; if (!describe_table(t->path, -1, -1, manifest, t->d, msg)) die("%s", msg.c_str()); identity_digest(t->d, t->identity); need += t->d.shard_size; logf("table %s: layer %d, %llu rows, weights @%llu, scales @%llu, identity %s", t->d.shard.c_str(), t->d.layer_id, (unsigned long long)t->d.rows(), (unsigned long long)t->d.weight.abs_offset, (unsigned long long)t->d.scale.abs_offset, hex(t->identity, 32).c_str()); g_svc.tables.push_back(std::move(t)); } // memory budget: the resident copies + the transport pools (per connection: 2 x max response + receive slots) const uint64_t pools = (uint64_t)listen.size() * 8 * 2 * ((uint64_t)max_rows * (kRowBytes + kScaleBytes) + (2u << 20)); const double need_gib = (need + pools) / 1073741824.0; const double avail_gib = meminfo_kb("MemAvailable") / 1048576.0; logf("memory: tables %.1f GiB + pools <= %.1f GiB = %.1f GiB; budget %.0f GiB; MemAvailable %.1f GiB (must keep %.0f)", need / 1073741824.0, pools / 1073741824.0, need_gib, budget_gib, avail_gib, reserve_gib); if (need_gib > budget_gib) die("%.1f GiB exceeds the budget of %.0f GiB", need_gib, budget_gib); if (avail_gib - need_gib < reserve_gib) die("loading would leave %.1f GiB available (< %.0f GiB reserve): refusing (never swap)", avail_gib - need_gib, reserve_gib); Hasher H; logf("sha256: %s; verify %s", H.ok ? "OpenSSL libcrypto" : "portable implementation", verify ? "on" : "OFF"); { std::vector lt; for (auto& t : g_svc.tables) lt.emplace_back([&H, &t, verify, readers] { load_table(*t, H, verify, readers); }); for (auto& x : lt) x.join(); } for (auto& t : g_svc.tables) logf("loaded %s in %.1f s (hash %.1f s)%s", t->d.shard.c_str(), t->load_s, t->hash_s, verify ? (", sha256 " + t->sha_actual + " = manifest").c_str() : ", NOT verified"); logf("resident: RSS %.1f GiB, AnonHugePages %.1f GiB, MemAvailable %.1f GiB", self_kb("VmRSS") / 1048576.0, meminfo_kb("AnonHugePages") / 1048576.0, meminfo_kb("MemAvailable") / 1048576.0); const int64_t pool_spin_us = atol(arg(argc, argv, "--pool-spin-us", "20000")); g_svc.pool.reset(threads > 0 ? new Pool(threads, pool_spin_us * 1000LL) : nullptr); std::vector servers; for (const auto& ip : listen) { ofl_server_config c{}; c.bind_ip = ip.c_str(); c.port = port; c.backends = (be.find("tcp") != std::string::npos ? 1 << OFL_BACKEND_TCP : 0) | (be.find("rdma") != std::string::npos ? 1 << OFL_BACKEND_RDMA : 0); c.gid_index = -1; c.service = kService; c.max_req_bytes = (uint32_t)(sizeof(LookupHdr) + 4ull * max_rows); c.max_resp_bytes = (uint32_t)((uint64_t)max_rows * (kRowBytes + kScaleBytes)); c.max_inflight = 2; c.max_conns = 8; c.spin_us = atol(arg(argc, argv, "--spin-us", "20000")); // then sleep on the completion channel char err[512]; ofl_server* s = ofl_server_create(&c, handler, nullptr, err, sizeof(err)); if (!s) die("listener %s: %s", ip.c_str(), err); ofl_server_start(s); logf("listening: %s", ofl_server_describe(s)); servers.push_back(s); } g_svc.ready.store(true); logf("ready (max %u rows a lookup, %d gather threads, inline up to %u rows, chunks of %u)", max_rows, threads, g_svc.inline_rows, g_svc.chunk_rows); int64_t last_stats = 0; while (!g_stop) { usleep(200000); if (!stats_path.empty() && now_ns() - last_stats > 5000000000LL) { last_stats = now_ns(); const std::string tmp = stats_path + ".tmp"; FILE* f = fopen(tmp.c_str(), "w"); if (f) { fputs(stats_json().c_str(), f); fputc('\n', f); fclose(f); rename(tmp.c_str(), stats_path.c_str()); } } } logf("stopping: %s", stats_json().c_str()); for (auto* s : servers) ofl_server_destroy(s); g_svc.pool.reset(); return 0; }