From 82da4c17404380a4d8dba1f7920008024e6d448b Mon Sep 17 00:00:00 2001 From: "Jona T. Feucht" <14951074+jonafeucht@users.noreply.github.com> Date: Sat, 9 Nov 2024 17:14:18 +0100 Subject: [PATCH 1/2] set opencl version --- Dockerfile.opencl.amd.rusticl | 94 ++++++++++++++++++++++++ README.md | 133 +++++++++++++++++++++++++++++++--- 2 files changed, 217 insertions(+), 10 deletions(-) create mode 100644 Dockerfile.opencl.amd.rusticl diff --git a/Dockerfile.opencl.amd.rusticl b/Dockerfile.opencl.amd.rusticl new file mode 100644 index 0000000..87760b3 --- /dev/null +++ b/Dockerfile.opencl.amd.rusticl @@ -0,0 +1,94 @@ +FROM ubuntu:noble + +ARG DEBIAN_FRONTEND=noninteractive + +USER root + +ARG PYTORCH_OCL_VERSION=0.2.0 +ARG TORCH_VERSION=2.4 +ARG PYTHON_VERSION=cp312 +ARG PLATFORM=linux_x86_64 + +ENV WHL_FILE=pytorch_ocl-${PYTORCH_OCL_VERSION}+torch${TORCH_VERSION}-${PYTHON_VERSION}-none-${PLATFORM}.whl +ENV WHL_URL=https://github.com/artyom-beilis/pytorch_dlprim/releases/download/${PYTORCH_OCL_VERSION}/${WHL_FILE} + +WORKDIR /app +COPY . /app + +RUN apt-get update && \ + apt install software-properties-common -y && \ + add-apt-repository ppa:kisak/kisak-mesa -y && \ + apt-get update -y && \ + apt dist-upgrade -y && \ + apt-get install -y \ + wget \ + software-properties-common \ + apt-transport-https \ + ca-certificates \ + curl \ + gpg && \ + rm -rf /var/lib/apt/lists/* + +# Install OpenCL dependencies +RUN apt-get update && apt-get install -y \ + ocl-icd-opencl-dev \ + opencl-headers \ + ocl-icd-libopencl1 \ + clinfo \ + mesa-opencl-icd \ + && rm -rf /var/lib/apt/lists/* + +# Install Python 3.12 +RUN add-apt-repository ppa:deadsnakes/ppa -y && \ + apt-get update && \ + apt-get install -y \ + python3.12 \ + python3.12-venv \ + python3.12-dev \ + python3-pip \ + && rm -rf /var/lib/apt/lists/* + +# Set up Python virtual environment +RUN python3.12 -m venv /app/venv +ENV PATH="/app/venv/bin:$PATH" +RUN pip install --upgrade pip + +# Install AMD GPU drivers +RUN apt update -y && \ + wget https://repo.radeon.com/amdgpu-install/6.2.3/ubuntu/noble/amdgpu-install_6.2.60203-1_all.deb && \ + apt install ./amdgpu-install_6.2.60203-1_all.deb -y && \ + rm -rf ./amdgpu-install_6.2.60203-1_all.deb + +# Configure OpenCL vendors +RUN mkdir -p /etc/OpenCL/vendors && \ + dpkg-divert --divert '/etc/OpenCL/vendors/mesa.icd.disabled' --rename '/etc/OpenCL/vendors/mesa.icd' && \ + echo "libamdocl64.so" > /etc/OpenCL/vendors/amdocl64.icd && \ + chmod 755 /etc/OpenCL/vendors + +RUN groupadd -f render && groupadd -f video +RUN usermod -a -G render,video root + +RUN mkdir -p /dev/dri && \ + touch /dev/dri/renderD128 && \ + chmod 666 /dev/dri/renderD128 + +RUN chmod 666 /dev/dri/render* || true +RUN chmod 666 /dev/dri/card* || true + +# Set environment variables for OpenCL +ENV OCL_ICD_VENDORS="/etc/OpenCL/vendors" +ENV OPENCL_VENDOR_PATH="/etc/OpenCL/vendors" + +ENV RUSTICL_ENABLE=radeonsi +ENV RUSTICL_CL_VERSION=2.1 +ENV RUSTICL_FEATURES=fp16,fp64 + +COPY requirements.txt /app/requirements.txt +RUN /app/venv/bin/pip install --no-cache-dir -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cpu + +# Install OpenCL backend for PyTorch +RUN wget ${WHL_URL} && \ + /app/venv/bin/pip install ${WHL_FILE} && \ + rm ${WHL_FILE} + +CMD ["/app/venv/bin/python", "-m", "fastapi", "run", "main.py", "--proxy-headers", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/README.md b/README.md index 6821155..872b6a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Image & Video Classification for NSFW and SFW media. +# Vision Classification for NSFW and SFW media. ## Stack: - [FastAPI](https://fastapi.tiangolo.com) @@ -9,7 +9,8 @@ - For ease of use it's recommended to use the provided [docker-compose.yml](https://github.com/doppeltilde/image_video_classification/blob/main/docker-compose.yml). -**CPU Support:** Use the `latest` tag. +### **CPU Support (AMD64 & ARM64)** +Use the `latest` tag. ```yml services: image_video_classification: @@ -17,7 +18,7 @@ services: ports: - "8000:8000" volumes: - - models:/root/.cache/huggingface/hub:rw + - ./models:/root/.cache/huggingface/hub:rw environment: - DEFAULT_MODEL_NAME - BATCH_SIZE @@ -26,12 +27,13 @@ services: - USE_API_KEYS - API_KEYS restart: unless-stopped - -volumes: - models: ``` -**NVIDIA GPU Support:** Use the `latest-cuda` tag. +### **NVIDIA GPU Support** +> [!IMPORTANT] +> Nvidia driver >=560 needs to be installed on the host machine. + +**CUDA (AMD64 & ARM64):** ```yml services: image_video_classification_cuda: @@ -39,7 +41,32 @@ services: ports: - "8000:8000" volumes: - - models:/root/.cache/huggingface/hub:rw + - ./models:/root/.cache/huggingface/hub:rw + environment: + - DEFAULT_MODEL_NAME + - BATCH_SIZE + - ACCESS_TOKEN + - DEFAULT_SCORE + - USE_API_KEYS + - API_KEYS + restart: unless-stopped + deploy: + resources: + reservations: + devices: + - driver: nvidia + count: all + capabilities: [ gpu ] +``` +**OpenCL (AMD64):** +```yml +services: + image_video_classification_opencl: + image: ghcr.io/doppeltilde/image_video_classification:latest-opencl-nvidia + ports: + - "8000:8000" + volumes: + - ./models:/root/.cache/huggingface/hub:rw environment: - DEFAULT_MODEL_NAME - BATCH_SIZE @@ -55,11 +82,73 @@ services: - driver: nvidia count: all capabilities: [ gpu ] +``` + +### **AMD GPU Support** +> [!WARNING] +> Unless AMD starts to officially support older cards again (e.g. gfx8), ROCm will not be available. -volumes: - models: +**OpenCL Rusticl (AMD64):** +> [!CAUTION] +> While Rusticl works on Polaris cards, there are significant differences in inference performance, with Polaris cards running Clover showing higher accuracy. + +```yml +services: + image_video_classification_cuda: + image: ghcr.io/doppeltilde/image_video_classification:latest-opencl-amd-rusticl + ports: + - "8000:8000" + volumes: + - ./models:/root/.cache/huggingface/hub:rw + - /tmp/.X11-unix:/tmp/.X11-unix + environment: + - DEFAULT_MODEL_NAME + - BATCH_SIZE + - ACCESS_TOKEN + - DEFAULT_SCORE + - USE_API_KEYS + - API_KEYS + restart: unless-stopped + devices: + - /dev/kfd + - /dev/dri + security_opt: + - seccomp:unconfined + group_add: + - "video" + - "render" +``` +**OpenCL Clover (AMD64):** +> [!CAUTION] +> Clover is only recommended for legacy cards (e.g. gfx8). If you're using gfx10 or newer, use Rusticl instead. +```yml +services: + image_video_classification_cuda: + image: ghcr.io/doppeltilde/image_video_classification:latest-opencl-amd-clover + ports: + - "8000:8000" + volumes: + - ./models:/root/.cache/huggingface/hub:rw + - /tmp/.X11-unix:/tmp/.X11-unix + environment: + - DEFAULT_MODEL_NAME + - BATCH_SIZE + - ACCESS_TOKEN + - DEFAULT_SCORE + - USE_API_KEYS + - API_KEYS + restart: unless-stopped + devices: + - /dev/kfd + - /dev/dri + security_opt: + - seccomp:unconfined + group_add: + - "video" + - "render" ``` +## Environment Variables - Create a `.env` file and set the preferred values. ```sh DEFAULT_MODEL_NAME=Falconsai/nsfw_image_detection @@ -75,6 +164,28 @@ USE_API_KEYS=False API_KEYS=abc,123,xyz ``` +## Tested Devices +Only tested with consumer grade hardware and only on Linux based systems. + +#### CPU +- AMD FX-6300 +- Intel Core i5-12400F +- AMD Ryzen 5 1600 +- AMD Ryzen 5 3600 +- AMD Ryzen 9 5950X + +#### NVIDIA GPU (CUDA & OpenCL) +- GTX 950 +- RTX 3060 Ti + +#### AMD GPU (OpenCL Clover & Rusticl) +- RX 570 4GB +- RX 580 8GB +- RX 6600 XT + +#### Intel GPU (OpenCL NEO) +- None + ## Models Any model designed for image classification and compatible with huggingface transformers should work. @@ -168,6 +279,8 @@ curl -X 'POST' \ > [!TIP] > You can find code examples in the [`examples`](./examples/) folder. +> [!IMPORTANT] +> Many thanks to Artyom Beilis and company for providing the awesome [OpenCL backend for PyTorch](https://github.com/artyom-beilis/pytorch_dlprim)! --- _Notice:_ _This project was initally created to be used in-house, as such the From 95de63dcf1c6d65e322d80bdd5991335c859a5b6 Mon Sep 17 00:00:00 2001 From: "Jona T. Feucht" <14951074+jonafeucht@users.noreply.github.com> Date: Sat, 9 Nov 2024 18:10:40 +0100 Subject: [PATCH 2/2] fix --- .github/workflows/prod.opencl.yml | 64 +++++++++++++++++++++++++++++++ .github/workflows/publish.yml | 9 ++--- 2 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/prod.opencl.yml diff --git a/.github/workflows/prod.opencl.yml b/.github/workflows/prod.opencl.yml new file mode 100644 index 0000000..d756c8f --- /dev/null +++ b/.github/workflows/prod.opencl.yml @@ -0,0 +1,64 @@ +name: OpenCL Production CI/CD + +on: + push: + tags: + - "v*" + branches: + - "main" + +env: + REGISTRY: "ghcr.io" + REGISTRY_USER: ${{ github.actor }} + REGISTRY_SECRET: ${{ secrets.GITHUB_TOKEN }} + IMAGE_NAME: ${{ github.repository }} + +permissions: + contents: read + packages: write + +jobs: + build_and_publish: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - docker_file: Dockerfile.opencl.nvidia + label: "latest-opencl-nvidia" + - docker_file: Dockerfile.opencl.amd.rusticl + label: "latest-opencl-amd-rusticl" + - docker_file: Dockerfile.opencl.amd.clover + label: "latest-opencl-amd-clover" + + steps: + - uses: actions/checkout@v4 + + - name: Meta + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=ref,event=tag + type=sha,prefix=sha- + type=raw,value=latest,enable=${{ matrix.label == 'latest' }} + labels: | + type=raw,value=image-type=${{ matrix.label }} + + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ env.REGISTRY_USER }} + password: ${{ env.REGISTRY_SECRET }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: ${{ matrix.docker_file }} + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64 \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5729903..8d8f70d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -22,7 +22,7 @@ jobs: matrix: include: - docker_file: Dockerfile - label: "latest" + label: "latest-cpu" - docker_file: Dockerfile.cuda label: "latest-cuda" steps: @@ -41,6 +41,7 @@ jobs: type=ref,event=pr type=ref,event=tag type=sha,prefix=sha- + type=raw,value=latest,enable=${{ matrix.label == 'latest' }} labels: | type=raw,value=image-type=${{ matrix.label }} @@ -56,8 +57,6 @@ jobs: context: . file: ${{ matrix.docker_file }} push: ${{ github.event_name != 'pull_request' }} - tags: | - ${{ steps.meta.outputs.tags }} - ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest${{ matrix.label =='latest-cuda' && '-cuda' || '' }} - # labels: ${{ steps.meta.outputs.labels }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64 \ No newline at end of file