RabbitMQに登録したメッセージからstable-diffusionを実行

フォルダの作成とdocker-composeの変更(WSL作業)

  1. 前回 の環境を変更していく
    画像input,outputフォルダの作成
work
├── Dockerfile
├── docker-compose.yml
├── src
│   ├── sample.py
│   ├── send_img2img.py
│   └── send_txt2img.py
├── inimg
├── outimg
│
 mkdir ./inimg
 mkdir ./outimg
  1. docker-composeの編集
    RabbitMQのコンテナの追加と画像フォルダの追加
    ローカルパス(\wsl$\Ubuntu-20.04\home\ubuntu)でWSL上のフォルダにアクセスできるため画像の置き換えが容易にできるようになる
    また、エクスプローラの特大アイコンで出力した画像が確認できるようになる
version: '3.6'
services:
  cuda:
    build:
      context: .
      dockerfile: Dockerfile
    runtime: nvidia
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
    tty: true
    volumes:
      - ./src:/src
      - ./inimg:/inimg
      - ./outimg:/outimg
    working_dir: /src
  rabbitmq:
      image: rabbitmq:3.8.14-management
      container_name: 'rabbitmq'
      restart: always
      ports:
          - 5672:5672
          - 15672:15672
      tty: true
  • 画像の削除などができなくなった場合は所有者を変更する
    (ubuntu:ubuntuはWSLの設定に合わせて変更する)
 sudo chown  ubuntu:ubuntu /inimg -R
 sudo chown  ubuntu:ubuntu /outimg -R

RabbitMQからメッセージを取得して実行するスクリプト(docker内作業)

  1. CUDA側のdockerコンテナにアタッチしてMQアクセス用のライブラリを取得しておく
 pip install pika
  1. ソースファイルの変更と作成
    sample.pyを以下のように変更する
# pip install pika

import os
import pika
workdir = "/work/stable-diffusion"

pika_param = pika.ConnectionParameters(host='rabbitmq', heartbeat=0)
connection = pika.BlockingConnection(pika_param)
channel = connection.channel()

channel.queue_declare(queue='txt2img')
channel.queue_declare(queue='img2img')

def img2img_callback(ch, method, properties, body):
  exeimg2img = " ".join(
      ["python"
    , "optimizedSD/optimized_img2img.py"])
  optimg2img = {
      "--prompt" : "Medium shot, alone, an anime girl"
    , "--init-img" : "/inimg/test.jpg"
    , "--outdir" : "/outimg"
    , "--strength" : "0.6"
    , "--n_samples" : "10"
    , "--H" : "512"
    , "--W" : "512"}

  if properties.headers is not None:
    # ヘッダの内容でオプションを置き換え、なければ作成
    for key in properties.headers:
      optimg2img[key] = properties.headers[key]
  # プロンプトだけは後でbodyで置き換え
  optimg2img["--prompt"] = "{}".format(str(body, 'utf-8'))

  exeimg2img = exeimg2img + " " + \
        " ".join("{} '{}'".format( \
            key, optimg2img[key]) for key in optimg2img)
  ch.basic_ack(delivery_tag = method.delivery_tag)

  print("img2img Start {}".format(str(body, 'utf-8')))
  os.system(exeimg2img)
  print("img2img End")


def txt2img_callback(ch, method, properties, body):
  exetxt2img = " ".join(
    ["python"
  , "optimizedSD/optimized_txt2img.py"])
  opttxt2img = {
    "--prompt" : ""
  , "--outdir" : "/outimg"
  , "--seed" : "27"
  , "--n_samples" : "10"
  , "--ddim_steps" : "50"
  , "--H" : "512"
  , "--W" : "512"}

  if properties.headers is not None:
    # ヘッダの内容でオプションを置き換え、なければ作成
    for key in properties.headers:
      opttxt2img[key] = properties.headers[key]
  # プロンプトだけは後でbodyで置き換え
  opttxt2img["--prompt"] = "{}".format(str(body, 'utf-8'))

  exetxt2img = exetxt2img + " " + \
        " ".join("{} '{}'".format( \
            key, opttxt2img[key]) for key in opttxt2img)
  ch.basic_ack(delivery_tag = method.delivery_tag)
  print("txt2img Start {}".format(str(body, 'utf-8')))
  os.system(exetxt2img)
  print("txt2img End")

channel.basic_consume(
    queue='txt2img', on_message_callback=txt2img_callback)
channel.basic_consume(
    queue='img2img', on_message_callback=img2img_callback)

os.chdir(workdir)
channel.start_consuming()
  1. send_img2img.pyを作成する
# pip install pika

from wsgiref import headers
import pika

pika_param = pika.ConnectionParameters(host='rabbitmq')
connection = pika.BlockingConnection(pika_param)
channel = connection.channel()

channel.queue_declare(queue='img2img')

opt=pika.BasicProperties(headers={'--init-img': '/inimg/hogehoge.png'})
channel.basic_publish(exchange='', routing_key='img2img', body='Anime, full body', properties=opt)

connection.close()
  • hogehoge.pngは予め用意しておく

  • send_txt2img.pyを作成する

# pip install pika

import pika

pika_param = pika.ConnectionParameters(host='rabbitmq')
connection = pika.BlockingConnection(pika_param)
channel = connection.channel()

channel.queue_declare(queue='txt2img')

channel.basic_publish(exchange='', routing_key='txt2img', body='Anime, full body')

connection.close()
  1. sample.pyを実行するとMQの監視が開始する
 python3 sample.py

メッセージの登録

Publish Message

WSL2上のDockerでStable Diffusionのimg2imgを動かす

前提条件

前回の内容のCUDA on WSLのインストール
nvidiaのインストールまでは済ませておく

dokcer-composeの実行

  1. フォルダ構成
work
├── Dockerfile
├── docker-compose.yml
├── src
│   ├── sample.py
  1. DockerComposeの編集
    version: '3.6'
    services:
    cuda:
        build:
        context: .
        dockerfile: Dockerfile
        runtime: nvidia
        environment:
        - NVIDIA_VISIBLE_DEVICES=all
        tty: true
        volumes:
        - ./src:/src
        working_dir: /src
  1. Dockerfile
    FROM nvidia/cuda:11.7.0-devel-rockylinux8

    RUN yum update -y
    RUN yum groupinstall "Development Tools" -y
    RUN yum install openssl-devel libffi-devel bzip2-devel wget git-lfs -y

    WORKDIR /root

    SHELL ["/bin/bash", "-c"]

    RUN wget https://repo.anaconda.com/miniconda/Miniconda3-4.7.12.1-Linux-x86_64.sh
    RUN bash Miniconda3-4.7.12.1-Linux-x86_64.sh  -b -p /opt/miniconda3
    ENV PATH /opt/miniconda3/bin:$PATH
    RUN conda init bash
    RUN conda update -n base -c defaults conda

    WORKDIR /work
    RUN mkdir stable-diffusion

    WORKDIR /work/stable-diffusion
    RUN git init
    RUN git pull https://github.com/basujindal/stable-diffusion.git

    RUN conda env create -f environment.yaml

    ENV CONDA_DEFAULT_ENV ldm
    RUN echo "conda activate ldm" >> ~/.bashrc
    ENV PATH /opt/conda/envs/ldm/bin:$PATH

    RUN conda install pytorch torchvision -c pytorch

    SHELL ["conda", "run", "-n", "ldm", "/bin/bash", "-c"]

    RUN pip install transformers==4.19.2 diffusers invisible-watermark
    RUN pip install -e .
  1. sample.pyの編集
    import torch

    print(torch.cuda.is_available())

docker-compose up を行う


起動したコンテナにアタッチしてimg2imgを実行する

  1. modelのダウンロード
 cd /work
 git clone https://huggingface.co/CompVis/stable-diffusion-v-1-4-original

 mkdir -p /work/stable-diffusion/models/ldm/stable-diffusion-v1/
 ln -s /work/stable-diffusion-v-1-4-original/sd-v1-4.ckpt /work/stable-diffusion/models/ldm/stable-diffusion-v1/model.ckpt

huggingfaceにユーザ登録をしておく
403エラーになる場合にはここにアクセスしてライセンスに同意する必要がある

  1. img2imgの実行
 cd /work/stable-diffusion/
 python scripts/img2img.py --prompt "Anime" --init-img stable-diffusion/inputs/test.png --strength 0.6 --n_samples 5 --H 512 --W 512

  • input file

    test.jpg

  • oupput file

    output

WSL2上のDockerでStable Diffusionを動かす

環境

Inspiron 7577
* Core i5-7300HQ
* GeForce GTX 1060(6GB MAX-Q)


WSLのアップデート

  1. ここを参考にPowerShellでWSLのアップデートを行う
 wsl --update

CUDA on WSLのインストール

  1. ここを参考にWSL内でCUDA ツールキットのインストール
    ただし、ここを参考にNO_PUBKEY BCD50790B81839D3の対策を入れておく
 sudo apt-key del 7fa2af80

 wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
 sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
 wget https://developer.download.nvidia.com/compute/cuda/11.7.0/local_installers/cuda-repo-wsl-ubuntu-11-7-local_11.7.0-1_amd64.deb
 sudo dpkg -i cuda-repo-wsl-ubuntu-11-7-local_11.7.0-1_amd64.deb

 sudo cp /var/cuda-repo-wsl-ubuntu-11-7-local/*.gpg /usr/share/keyrings/

 sudo apt-get update
 sudo apt-get -y install cuda
  1. nvidia-dockerのインストール
    ここを参考にnvidia-docker2のインストールを行う
  sudo apt remove docker-ce docker-ce-cli containerd.io -y

  distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
    && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
    && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

  sudo apt-get update
  sudo apt-get install -y nvidia-docker2 docker-compose-plugin
  sudo /etc/init.d/docker restart

docker-composeの実行

  1. docker-composeファイルを作成してup
    ここを参考にNVIDIA_VISIBLE_DEVICES=allをつけておく
  version: '3.6'
  services:
    cuda:
      image: nvidia/cuda:11.7.0-devel-rockylinux8
      runtime: nvidia
      environment:
        - NVIDIA_VISIBLE_DEVICES=all
      tty: true
      volumes:
        - ./src:/src
      working_dir: /src
  1. ここここを参考にpython3のインストールと設定
    python3.10がほしい
 yum update
 yum groupinstall "Development Tools" -y
 yum install openssl-devel libffi-devel bzip2-devel wget -y
 wget https://www.python.org/ftp/python/3.10.6/Python-3.10.6.tgz

 tar xvf Python-3.10.6.tgz
 cd Python-3.10.6

 ./configure --enable-optimizations
 make altinstall

 pip3.10 install torch torchvision

python3でGPUが使えるか確認(Trueが帰ってくればOK)

 python3.10
   >> import torch
   >> print(torch.cuda.is_available())
  1. ここを参考にStable Diffusionを使えるようにしていく
    ユーザ登録を行いアクセストークンを取得しておくこと アクセストークンの種類はREADで行けた
pip3.10 install diffusers==0.2.4 transformers scipy ftfy
 python3.10
   >> import torch
   >> from diffusers import StableDiffusionPipeline
   >> pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", revision="fp16", torch_dtype=torch.float16, use_auth_token="hf_*****************")
   >> pipe = pipe.to("cuda")
   >> prompt = "a photograph of an astronaut riding a horse"
   >> from torch import autocast
   >> with autocast("cuda"):
   >>   image = pipe(prompt)["sample"][0]
   >> image.save(f"image_name.png")
  • auth_tokenは自前のものを使う

    別の画像を作成したい場合は途中から書けばいいらしい

   >> prompt="a beautiful mountain landscape"
   >> from torch import autocast
   >> with autocast("cuda"):
   >>   image = pipe(prompt)["sample"][0]
   >> image.save(f"image_name2.png")
   >> exit()

WSL2 on dockerの立ち上げ

仮想環境のチェック

タスクマネージャーを立ち上げて[詳細]表示にしてパフォーマンスタブの右下の仮想化が有効であることを確認


WSL2-Ubuntu20.04のインストール(windows 10)

  1. ここを参考にWSL2のインストール

     dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
    
  2. Linuxカーネル更新

    ここカーネル更新プログラムのインストール

     wsl --set-default-version 2
    
  3. ウィンドウズストアからUbuntsu20.04のインストール

  4. ここを参考にWSLイメージの置き場所を変更する

     d:
     mkdir d:\work\wsl-backup
     mkdir d:\work\Ubuntu-20.04
     cd d:\work\wsl-backup
     wsl --export Ubuntu-20.04 d:\work\wsl-backup\export.tar
     wsl --unregister Ubuntu-20.04
     wsl --import Ubuntu-20.04 d:\work\Ubuntu-20.04\ d:\work\wsl-backup\export.tar --version 2
     rm d:\work\wsl-backup\
     wsl -l -v
    

    regeditを立ち上げHKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss配下のDistributionNameUbuntu-20.04の項目のDefaultUidを1000(10進)に書き換え

  5. ここを参考にdockerのインストール

     sudo apt update
    
     sudo apt-get install ca-certificates curl gnupg lsb-release -y
    
     sudo mkdir -p /etc/apt/keyrings
    
     curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    
     echo \
       "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
       $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
     sudo apt-get update
    
     sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
    
     docker --version
    
  6. ここを参考にdockerのユーザ追加と起動時実行を設定

     sudo usermod -aG docker $USER
    
     cat <<EOF >> ~/.bashrc
     sudo /etc/init.d/docker start
     EOF
    
  7. WSL再起動後に動作確認(ウィンドウを閉じて開くだけ)
    WSL起動時にパスワードを聞かれるようになる(sudoでdockerをstartさせるので)

      docker run hello-world