{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "intro",
      "metadata": {},
      "source": "# Cases C, D and E: one computation, three execution policies\n\nThis live Aner notebook uses **100,003 draws** as an explicit teaching preset. It retains ten counts per block and checks every retained block/bin and derived seed identity against Case C. These histogram checks do not claim to retain or compare every individual observation.\n\nOpen the project root, choose **Aner — notebook**, **Shared variables** and **Prod**, then run cells in order. No saved outputs or measured results are bundled. Changing the seed, count, block size or function requires a fresh session followed by Run All. The matching development runtime must support the selected native process/SSH cluster transport.\n\nThis is one interactive comparison without excluded warmups. Use [the benchmark](../benchmarks/benchmark_native.aner) for the full 100,000,003-draw, 12-round study. Notebook timings are not that study's results."
    },
    {
      "cell_type": "code",
      "id": "setup",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "import aner.parallel\nimport aner.random\n\nlet draw_count = 100_003\nlet block_size = 10_000\nlet root_seed = 20_261_019\nlet local_workers = 4\nlet enable_cluster = false // Set true only after preparing the private 4+4 config.\nlet cluster_config = \"config/cluster.private\"\nlet blocks = integer_div(draw_count + block_size - 1, block_size)\nlet parameters = List(draw_count, block_size, root_seed)\n"
    },
    {
      "cell_type": "markdown",
      "id": "task-notes",
      "metadata": {},
      "source": "## Shared task\n\nThe same root seed and global draw identity select the same integer in all three cases. Scheduling changes execution placement. Only the ten histogram counts from each block are retained or returned; the final block contains three accepted draws."
    },
    {
      "cell_type": "code",
      "id": "task",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "// The root seed and global draw index select each observation independently\n// of task scheduling. Retain ten counts per block, without transferring draws.\nfn count_block(parameters: List, block: Int64, task_seed: Int64) -> List {\n    let count = cast<Int64>(parameters.get(0))\n    let size = cast<Int64>(parameters.get(1))\n    let seed = cast<Int64>(parameters.get(2))\n    let counts = Array<Int64>(10, 0)\n    for offset in Range(size) {\n        let draw = block * size + offset\n        if draw < count {\n            let choice = random.integer(low: 1, high: 10, seed: seed, draw: draw)\n            counts[choice - 1] += 1\n        }\n    }\n    let output = List()\n    for face in Range(10) { output.append(counts[face]) }\n    return output\n}\n"
    },
    {
      "cell_type": "markdown",
      "id": "case-c-notes",
      "metadata": {},
      "source": "## C · one local native worker\n\nThe timer surrounds only the native repetition call. Reduction and comparison run after generation."
    },
    {
      "cell_type": "code",
      "id": "case-c",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "let serial_execution = parallel.local(workers: 1)\nlet started_c = Duration.monotonic()\nlet results_c = parallel.repeat(iterations: blocks, task: count_block,\n    parameters: parameters, execution: serial_execution, seed: root_seed,\n    max_bytes: 67_108_864)\nlet elapsed_c_ns = Duration.monotonic().subtract(started_c).nanoseconds()\nprint(\"Case C repeat elapsed_ns=\" + String(elapsed_c_ns))\nprint(results_c.summary())\n"
    },
    {
      "cell_type": "markdown",
      "id": "case-d-notes",
      "metadata": {},
      "source": "## D · four local native workers\n\nCase D uses the same task, parameters and addressed observations as C."
    },
    {
      "cell_type": "code",
      "id": "case-d",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "let parallel_execution = parallel.local(workers: local_workers)\nlet started_d = Duration.monotonic()\nlet results_d = parallel.repeat(iterations: blocks, task: count_block,\n    parameters: parameters, execution: parallel_execution, seed: root_seed,\n    max_bytes: 67_108_864)\nlet elapsed_d_ns = Duration.monotonic().subtract(started_d).nanoseconds()\nprint(\"Case D repeat elapsed_ns=\" + String(elapsed_d_ns))\nprint(results_d.summary())\n"
    },
    {
      "cell_type": "markdown",
      "id": "verify-notes",
      "metadata": {},
      "source": "## Verify C and D\n\nCompare every block/bin and every derived seed identity outside the timers, then reduce the ten-bin histogram. A mismatch stops execution."
    },
    {
      "cell_type": "code",
      "id": "verify",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "var mismatched_cd_cells = 0\nvar mismatched_cd_seeds = 0\nlet histogram_c = Array<Int64>(10, 0)\nfor block in Range(blocks) {\n    if results_c.seed(block) != results_d.seed(block) { mismatched_cd_seeds += 1 }\n    for face in Range(10) {\n        if results_c.value(block, face) != results_d.value(block, face) { mismatched_cd_cells += 1 }\n        histogram_c[face] += Int64(results_c.value(block, face))\n    }\n}\nvar counted_c = 0\nfor face in Range(10) { counted_c += histogram_c[face] }\nif mismatched_cd_cells != 0 || mismatched_cd_seeds != 0 || counted_c != draw_count {\n    print(\"FAILED: C/D parity or draw accounting\")\n    print(integer_div(1, 0))\n}\nprint(\"C/D exact retained block/bin and seed parity: \" + String(blocks * 10) + \" cells\")\nprint(histogram_c)\n"
    },
    {
      "cell_type": "markdown",
      "id": "case-e-notes",
      "metadata": {},
      "source": "## E · four workers on each of two computers\n\nThis cell is skipped while enable_cluster is false. Copy [the config template](../config/cluster.example) to the private path, install compatible runtimes, and establish authenticated, known-host SSH before opting in. Use the actual absolute runtime paths and an SSH alias in your private config. The timer includes native cluster connection, admission, work and teardown. It excludes validation.\n\nThe runtime prints per-node **task** counts. The node that owns the three-draw final block is not identified by that summary, so task counts are not exact per-node draw counts."
    },
    {
      "cell_type": "code",
      "id": "case-e",
      "metadata": {},
      "execution_count": null,
      "outputs": [],
      "source": "if enable_cluster {\n    let cluster_execution = parallel.cluster(config: cluster_config)\n    let started_e = Duration.monotonic()\n    let results_e = parallel.repeat(iterations: blocks, task: count_block,\n        parameters: parameters, execution: cluster_execution, seed: root_seed,\n        max_bytes: 67_108_864)\n    let elapsed_e_ns = Duration.monotonic().subtract(started_e).nanoseconds()\n    var mismatched_e_cells = 0\n    var mismatched_e_seeds = 0\n    for block in Range(blocks) {\n        if results_c.seed(block) != results_e.seed(block) { mismatched_e_seeds += 1 }\n        for face in Range(10) {\n            if results_c.value(block, face) != results_e.value(block, face) { mismatched_e_cells += 1 }\n        }\n    }\n    if mismatched_e_cells != 0 || mismatched_e_seeds != 0 {\n        print(\"FAILED: C/E parity\")\n        print(integer_div(1, 0))\n    }\n    print(\"Case E repeat elapsed_ns=\" + String(elapsed_e_ns))\n    print(\"C/E exact retained block/bin and seed parity: \" + String(blocks * 10) + \" cells\")\n    print(results_e.summary())\n} else {\n    print(\"Case E skipped: enable the prepared private cluster configuration explicitly\")\n}\n"
    },
    {
      "cell_type": "markdown",
      "id": "next",
      "metadata": {},
      "source": "## Reproduce the measured study\n\nThe [benchmark source](../benchmarks/benchmark_native.aner) runs one complete serial reference, one excluded 80,000-draw warmup before each measured arm, and 12 rotated rounds of C/D/E. Every trial checks all 100,010 retained histogram cells and 10,001 derived seed identities against the shared reference. The CLI needs the documented large top-level step budget; notebook cells keep their native session limits.\n\nLocal native pools are retained; cluster repeats establish new worker sessions. The primary metric is repeat-call wall time. A whole benchmark command also includes the shared reference, all warmups and validation. See [the project README](../README.md) for provenance and the measured results."
    }
  ],
  "metadata": {
    "kernelspec": {
      "name": "aner",
      "display_name": "Aner",
      "language": "aner"
    },
    "language_info": {
      "name": "aner",
      "file_extension": ".aner",
      "mimetype": "text/x-aner"
    },
    "aner": {
      "execution_mode": "persistent-session",
      "runtime_mode": "production",
      "source_file": "../benchmarks/benchmark_native.aner",
      "status": "live-source-only"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
