{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "# 01 AMD ROCm 设备与环境确认\n\n        这一节的目标是先证明设备、环境、缓存和权限链路是可用的。很多训练失败看起来像模型问题，实际可能是 ROCm 没识别 GPU、缓存放错磁盘、网络无法下载权重，或者统一内存被其它进程挤占。\n\n        Notebook 里主要做三件事：检查硬件和 PyTorch、规划大文件目录、形成一张设备资源表。\n"
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": "from pathlib import Path\nimport json\nimport os\nimport shutil\nimport subprocess\nimport sys\n\n\ndef find_topic_root():\n    cwd = Path.cwd().resolve()\n    for candidate in [cwd, *cwd.parents]:\n        if (candidate / \"assets\" / \"metrics_snapshot.json\").exists():\n            return candidate\n    raise RuntimeError(\"请从 AMD ROCm 专题目录或 notebooks 子目录启动 Jupyter。\")\n\n\nTOPIC_ROOT = find_topic_root()\nASSET_DIR = TOPIC_ROOT / \"assets\"\nNOTEBOOK_DIR = TOPIC_ROOT / \"notebooks\"\nPROJECT_ROOT = Path(os.environ.get(\"PROJECT_ROOT\", \"/path/to/every-embodied/mujoco_pnp\"))\nDATA_ROOT = Path(os.environ.get(\"DATA_ROOT\", \"/path/to/datasets/every_embodied\"))\nOUTPUT_ROOT = Path(os.environ.get(\"OUTPUT_ROOT\", TOPIC_ROOT / \"outputs\"))\nMODEL_ROOT = Path(os.environ.get(\"MODEL_ROOT\", PROJECT_ROOT / \"ckpt\"))\n\nprint(\"TOPIC_ROOT =\", TOPIC_ROOT)\nprint(\"PROJECT_ROOT =\", PROJECT_ROOT)\nprint(\"DATA_ROOT =\", DATA_ROOT)\nprint(\"OUTPUT_ROOT =\", OUTPUT_ROOT)\nprint(\"MODEL_ROOT =\", MODEL_ROOT)\n"
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": "try:\n    from IPython.display import Image, Markdown, display\nexcept Exception:\n    class Markdown(str):\n        pass\n\n    def display(obj):\n        print(obj)\n\n    def Image(filename=None, width=None):\n        return f\"[image] {filename}\"\n\n\ndef show_asset(filename, width=960):\n    path = ASSET_DIR / filename\n    if path.exists():\n        display(Image(filename=str(path), width=width))\n    else:\n        print(f\"缺少素材：{path}\")\n\n\ndef md_table(headers, rows):\n    lines = [\"| \" + \" | \".join(headers) + \" |\", \"| \" + \" | \".join([\"---\"] * len(headers)) + \" |\"]\n    for row in rows:\n        lines.append(\"| \" + \" | \".join(str(x) for x in row) + \" |\")\n    display(Markdown(\"\\n\".join(lines)))\n"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Checkpoint 1：ROCm 和 PyTorch 是否能看到 GPU\n"
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": "def run_cmd(cmd):\n    print(\"$\", \" \".join(cmd))\n    if shutil.which(cmd[0]) is None:\n        print(f\"未找到命令：{cmd[0]}\")\n        return\n    result = subprocess.run(cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n    print(result.stdout)\n\n\nrun_cmd([\"rocm-smi\", \"--showuse\", \"--showtemp\", \"--showmemuse\"])\n\ntry:\n    import torch\n    print(\"torch =\", torch.__version__)\n    print(\"torch.cuda.is_available() =\", torch.cuda.is_available())\n    print(\"torch.cuda.device_count() =\", torch.cuda.device_count())\n    if torch.cuda.is_available():\n        print(\"device =\", torch.cuda.get_device_name(0))\nexcept Exception as exc:\n    print(\"PyTorch 检查失败：\", repr(exc))\n"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "如果 `rocm-smi` 正常、`torch.cuda.is_available()` 为 `True`，说明 ROCm 与 PyTorch 的基础链路已经打通。若前者正常但后者为 `False`，优先检查 PyTorch 是否为 ROCm build。\n"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Checkpoint 2：统一内存、显存和磁盘目录\n"
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": "paths = [\n    (\"项目源码\", PROJECT_ROOT),\n    (\"数据目录\", DATA_ROOT),\n    (\"模型与 checkpoint\", MODEL_ROOT),\n    (\"Notebook 输出\", OUTPUT_ROOT),\n    (\"Hugging Face cache\", Path(os.environ.get(\"HF_HOME\", \"/path/to/cache/huggingface\"))),\n]\nmd_table([\"项目\", \"建议路径\", \"是否存在\"], [(name, f\"`{path}`\", path.exists()) for name, path in paths])\n"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "大模型缓存、数据集、checkpoint 和批量视频都可能很大。实验报告里说明目录规划和磁盘类型即可，不需要把这些文件放进教程目录。\n"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "## Checkpoint 3：设备资源表模板\n"
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": "rows = [\n    (\"设备型号\", \"AMD Ryzen AI MAX+ / Radeon GPU\"),\n    (\"系统版本\", \"Ubuntu / WSL / 其它\"),\n    (\"ROCm 版本\", \"填写 rocm-smi 或包版本\"),\n    (\"PyTorch 版本\", \"填写 torch.__version__\"),\n    (\"空闲温度\", \"例如 30-45 C\"),\n    (\"训练温度\", \"例如 75-85 C\"),\n    (\"ACT 训练 VRAM\", \"填写 rocm-smi 观察值\"),\n    (\"SmolVLA 训练 VRAM\", \"填写 rocm-smi 观察值\"),\n    (\"pi0 smoke 状态\", \"未跑 / 通过 / 失败原因\"),\n]\nmd_table([\"项目\", \"记录\"], rows)\n"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": "完成本节后，应当能判断这台 AMD 设备是否已经具备继续训练和评估的条件。\n"
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
