diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index d1e18683..11f9dbb1 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -79,7 +79,9 @@ jobs: build-and-test: needs: ensure-base - runs-on: self-hosted + # App image build runs on a GitHub-hosted runner: the CPU-only image is small + # and ensure-base already builds the heavier base image on ubuntu-latest. + runs-on: ubuntu-latest permissions: contents: read diff --git a/.github/workflows/pytorchsim_test.yml b/.github/workflows/pytorchsim_test.yml index da8366af..98dbd791 100644 --- a/.github/workflows/pytorchsim_test.yml +++ b/.github/workflows/pytorchsim_test.yml @@ -15,10 +15,14 @@ on: required: true type: number +# Runner policy: the CPU-only CI image is small enough to pull on GitHub-hosted +# runners, so op and model tests run on ubuntu-latest. The memory/time-intensive +# jobs stay on self-hosted: test_deepseek (largest model), test_diffusion (UNet2D +# simulation OOMs the hosted runner), and test_accuracy (accuracy + speedup). jobs: test_add: name: Run test_add.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -37,7 +41,7 @@ jobs: test_transcendental: name: Run test_transcendental.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -56,7 +60,7 @@ jobs: test_activation: name: Run test_activation.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -75,7 +79,7 @@ jobs: test_batchnorm: name: Run test_batchnorm.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -94,7 +98,7 @@ jobs: test_bmm: name: Run test_bmm.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -113,7 +117,7 @@ jobs: test_cnn: name: Run test_cnn.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -132,7 +136,7 @@ jobs: test_conv2d: name: Run test_conv2d.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -151,7 +155,7 @@ jobs: test_cat: name: Run test_cat.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -170,7 +174,7 @@ jobs: test_matmul: name: Run test_matmul.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -189,7 +193,7 @@ jobs: test_reduce: name: Run test_reduce.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -208,7 +212,7 @@ jobs: test_softmax: name: Run test_softmax.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -227,7 +231,7 @@ jobs: test_transpose2D: name: Run test_transpose2D.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -246,7 +250,7 @@ jobs: test_view3D_2D: name: Run test_view3D_2D.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -265,7 +269,7 @@ jobs: test_layernorm: name: Run test_layernorm.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -284,7 +288,7 @@ jobs: test_mlp: name: Run test_mlp.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -303,7 +307,7 @@ jobs: test_resnet: name: Run test_resnet.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -330,7 +334,7 @@ jobs: test_mobilenet: name: Run test_mobilenet.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -349,7 +353,7 @@ jobs: test_transformer: name: Run test_transformer.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -368,7 +372,7 @@ jobs: test_transpose3D: name: Run test_transpose3D.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -387,7 +391,7 @@ jobs: test_sparsity: name: Run test_sparsity.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -406,7 +410,7 @@ jobs: test_pool: name: Run test_pool.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -425,7 +429,7 @@ jobs: test_perceptron: name: Run test_perceptron.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -444,7 +448,7 @@ jobs: test_fusion: name: Run test_fusion - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -535,7 +539,7 @@ jobs: test_moe: name: Run test_moe - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -554,7 +558,7 @@ jobs: test_mistral: name: Run test_mistral - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -573,7 +577,7 @@ jobs: test_vit: name: Run test_vit - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -592,6 +596,8 @@ jobs: test_diffusion: name: Run test_diffusion + # UNet2DConditionModel simulation exceeds the GitHub-hosted memory limit + # (Spike gets OOM-killed), so keep it on a self-hosted runner. runs-on: self-hosted steps: - name: Log in to GitHub Container Registry @@ -611,7 +617,7 @@ jobs: test_indirect: name: Run test_indirect - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -630,7 +636,7 @@ jobs: test_scheduler: name: Run test_scheduler - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -649,7 +655,7 @@ jobs: test_llama: name: Run test_llama1&2 - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -668,7 +674,7 @@ jobs: test_yolov5: name: Run test_yolov5 - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -687,6 +693,8 @@ jobs: test_deepseek: name: Run test_deepseek + # DeepSeek-V3 is the largest model under test; keep it on a self-hosted + # runner to avoid the GitHub-hosted memory limit. runs-on: self-hosted steps: - name: Log in to GitHub Container Registry @@ -706,7 +714,7 @@ jobs: test_eager: name: Run test_eager.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -725,7 +733,7 @@ jobs: test_exponent: name: Run test_exponent.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -744,7 +752,7 @@ jobs: test_sort: name: Run test_sort.py - runs-on: self-hosted + runs-on: ubuntu-latest steps: - name: Log in to GitHub Container Registry uses: docker/login-action@v3 @@ -763,6 +771,8 @@ jobs: test_accuracy: name: Run test_accuracy and test_speedup + # Accuracy + speedup runs many model simulations end to end; it is the most + # time- and memory-intensive job, so keep it on a self-hosted runner. runs-on: self-hosted if: inputs.vector_lane == 128 steps: diff --git a/Dockerfile.base b/Dockerfile.base index 05444d41..19bbbb2e 100644 --- a/Dockerfile.base +++ b/Dockerfile.base @@ -23,35 +23,50 @@ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -ARG PYTORCH_IMAGE=pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtime +# CPU-only base. PyTorchSim never executes CUDA: the npu PrivateUse1 backend +# (third_party/openreg) simulates CUDA behavior on the CPU and forces math-only +# SDPA, so no GPU libraries are needed at build or run time. We stay on +# ubuntu:22.04 (matching the prebuilt gem5/llvm/spike release ABIs: libpython3.11, +# libprotobuf.so.23) and install the CPU PyTorch wheels. +ARG PYTORCH_IMAGE=ubuntu:22.04 FROM ${PYTORCH_IMAGE} -# Copied from Gem5 Docker file ENV DEBIAN_FRONTEND=noninteractive -RUN apt -y update && \ - apt -y install build-essential git m4 zlib1g zlib1g-dev \ - libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ - python3-dev python-is-python3 libboost-all-dev \ - libhdf5-serial-dev python3-pydot libpng-dev libelf-dev pkg-config pip \ - python3-venv black libssl-dev libasan5 libubsan1 curl device-tree-compiler wget ninja-build && \ - pip install onnx matplotlib scikit-learn pydot tabulate flash_attn && pip install --user conan==1.56.0 cmake==3.26.4 && rm -rf /var/lib/apt/lists/* +WORKDIR /workspace -# Download RISC-V tool chain -RUN wget https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.12.14/riscv64-glibc-ubuntu-22.04-llvm-nightly-2023.12.14-nightly.tar.gz && \ - wget https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.12.14/riscv64-elf-ubuntu-20.04-llvm-nightly-2023.12.14-nightly.tar.gz && \ - tar -zxvf riscv64-elf-ubuntu-20.04-llvm-nightly-2023.12.14-nightly.tar.gz && tar -zxvf riscv64-elf-ubuntu-20.04-llvm-nightly-2023.12.14-nightly.tar.gz && \ - rm *.tar.gz +# System dependencies (gem5 / TOGSim build + runtime) and Python 3.11 (deadsnakes). +# Copied/adapted from the Gem5 Docker file. +RUN apt-get -y update && \ + apt-get -y install software-properties-common ca-certificates gnupg && \ + add-apt-repository -y ppa:deadsnakes/ppa && \ + apt-get -y update && \ + apt-get -y install build-essential git m4 zlib1g zlib1g-dev \ + libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev \ + libboost-all-dev libhdf5-serial-dev libpng-dev libelf-dev pkg-config \ + libssl-dev libasan6 libubsan1 curl wget device-tree-compiler ninja-build \ + python3.11 python3.11-dev python3.11-venv python3.11-distutils && \ + update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.11 1 && \ + update-alternatives --install /usr/bin/python python /usr/bin/python3.11 1 && \ + curl -sS https://bootstrap.pypa.io/get-pip.py | python3.11 && \ + rm -rf /var/lib/apt/lists/* -# Install torchsim dependency -RUN apt install ninja-build && pip install onnx matplotlib && pip install --user conan==1.56.0 && pip install "transformers<4.44" && pip install diffusers==0.34.0 +# CPU PyTorch (no CUDA wheels). torchvision is required by the vision model tests. +RUN python3.11 -m pip install --no-cache-dir \ + torch==2.8.0 torchvision==0.23.0 --index-url https://download.pytorch.org/whl/cpu -# FlashAttention -RUN python -m pip install --no-build-isolation flash-attn +# TorchSim Python dependencies (numpy pinned <2 for transformers/diffusers compat). +RUN python3.11 -m pip install --no-cache-dir \ + "numpy<2" onnx matplotlib scikit-learn pydot tabulate \ + "transformers<4.44" diffusers==0.34.0 \ + conan==1.56.0 cmake==3.26.4 && \ + python3.11 -m pip install --no-cache-dir --no-deps ultralytics && \ + python3.11 -m pip install --no-cache-dir opencv-python-headless pandas seaborn \ + psutil pyyaml requests tqdm py-cpuinfo -# Extra Python deps for YOLO/vision tests -RUN python -m pip install -U pip setuptools wheel && \ - python -m pip install --no-cache-dir --no-deps ultralytics && \ - python -m pip install --no-cache-dir opencv-python-headless pandas seaborn +# Download RISC-V tool chain (elf toolchain is the one used to build riscv-pk). +RUN wget -q https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2023.12.14/riscv64-elf-ubuntu-20.04-llvm-nightly-2023.12.14-nightly.tar.gz && \ + tar -zxf riscv64-elf-ubuntu-20.04-llvm-nightly-2023.12.14-nightly.tar.gz && \ + rm riscv64-elf-ubuntu-20.04-llvm-nightly-2023.12.14-nightly.tar.gz ENV RISCV=/workspace/riscv ENV PATH=$RISCV/bin:$PATH @@ -60,7 +75,7 @@ ARG GEM5_ASSET_ID ARG LLVM_ASSET_ID ARG SPIKE_ASSET_ID ENV PATH=$PATH:/root/.local/bin -ENV LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/opt/conda/lib:/usr/local/nvidia/lib:/usr/local/nvidia/lib64:$LD_LIBRARY_PATH +ENV LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH # Download GEM5 for torchsim RUN curl -L -H "Accept: application/octet-stream" https://api.github.com/repos/PSAL-POSTECH/gem5/releases/assets/${GEM5_ASSET_ID} -o /tmp/gem5-release.tar.gz && \ diff --git a/tests/models/DeepSeek/test_deepseek_v3_base.py b/tests/models/DeepSeek/test_deepseek_v3_base.py index 5005b70b..2941e776 100644 --- a/tests/models/DeepSeek/test_deepseek_v3_base.py +++ b/tests/models/DeepSeek/test_deepseek_v3_base.py @@ -7,6 +7,37 @@ sys.path.insert(0, os.path.join(os.environ.get("TORCHSIM_DIR", default="/workspace/PyTorchSim"), "tests")) from _pytorchsim_utils import test_result +# DeepSeek-V3's remote modeling file (trust_remote_code) imports flash_attn, and +# transformers' check_imports statically requires it to be installed even though +# the npu backend never runs flash attention (math-only SDPA). The CI image is +# CPU-only and has no flash_attn, so register an import shim: it satisfies the +# static import check and any flash_attn[.submodule] import. It deliberately +# provides no package metadata, so transformers' is_flash_attn_2_available() +# stays False and the model selects the eager/sdpa path. +import importlib.abc +import importlib.util +import types + + +class _FlashAttnShim(importlib.abc.MetaPathFinder, importlib.abc.Loader): + def find_spec(self, name, path=None, target=None): + if name == "flash_attn" or name.startswith("flash_attn."): + return importlib.util.spec_from_loader(name, self, is_package=True) + return None + + def create_module(self, spec): + module = types.ModuleType(spec.name) + module.__path__ = [] + module.__getattr__ = lambda _name: None + return module + + def exec_module(self, module): + pass + + +if importlib.util.find_spec("flash_attn") is None: + sys.meta_path.insert(0, _FlashAttnShim()) + # recursive compile for some ops that are caused by graph break torch.npu.register_eager_to_compile([ "aten::zero_", diff --git a/thirdparty/github-releases.json b/thirdparty/github-releases.json index ec89c24f..3e836f2e 100644 --- a/thirdparty/github-releases.json +++ b/thirdparty/github-releases.json @@ -1,6 +1,6 @@ { - "description": "GitHub release pins for CI (docker base image). pytorch_image is the ARG PYTORCH_IMAGE for Dockerfile.base. Use release_tag \"latest\" or an exact release tag for GitHub deps. asset_name must match the release attachment filename. CI builds ghcr.io/.../torchsim_base:thirdparty-<12 hex> when missing (pin = sha256 of this file plus Dockerfile.base) and updates :latest on that push.", - "pytorch_image": "pytorch/pytorch:2.8.0-cuda12.6-cudnn9-devel", + "description": "GitHub release pins for CI (docker base image). pytorch_image is the ARG PYTORCH_IMAGE (FROM base) for Dockerfile.base; PyTorchSim is CPU-only (the npu PrivateUse1 backend simulates CUDA on the CPU), so the CPU PyTorch wheels are installed on top of a plain ubuntu base. Use release_tag \"latest\" or an exact release tag for GitHub deps. asset_name must match the release attachment filename. CI builds ghcr.io/.../torchsim_base:thirdparty-<12 hex> when missing (pin = sha256 of this file plus Dockerfile.base) and updates :latest on that push.", + "pytorch_image": "ubuntu:22.04", "gem5": { "repository": "PSAL-POSTECH/gem5", "release_tag": "v1.0.1",