Python ReactiveXのtimerが値を出さない

ReactiveXのコード読んでないので理由不明ですが、reactivex.timer()Link はdue timeにdatetime.datetime型を指定した場合、値を出さない。GILLink とかasyncioという話でもなさそう。

import datetime
import reactivex as rx

import time
import asyncio

dtStart = datetime.datetime.now() + datetime.timedelta(seconds=10)
rx.timer(dtStart, 5).subscribe(
    on_next = lambda value: print(value),  # 呼ばれない
    on_completed = lambda: print('completed'),
    on_error = lambda ex: print(ex)
)

time.sleep(30)
# asyncio.run(asyncio.sleep(30))  # こちらでも同じなので、GILのせいではなさそう
回避策として、due timeから現時刻を引き算して渡す。
rx.timer(dtStart - datetime.datetime.now(), 5)  # これは値を出す
環境
  • WinPython 3.12.2 64bit
  • reactivex 4.0.4

— posted by mu at 02:30 pm   commentComment [0]  pingTrackBack [0]

RX570/Ubuntu 22.04でFooocusを動かす

先日Link の続き。Stable Diffusion XLの派生Fooocusが動くまでこぎつけたので、備忘録。

環境

  • CPU: Ryzen 1700。お古を流用。PCIe atomic機能を有するHaswell以降・初代Ryzen以降必須。Fooocusはシングルスレッド性能しか求めてないようなので、選べるならそちら重視で。
  • OS: Ubuntu 22.4 LTS。参考にしたサイトの情報だとカーネル5.xなら動きそうな感じはするので、22.4, 22.4.1, 22.4.2は行けるかも。カーネル6.xになる22.4.3は実際にやって失敗した(Radeonドライバが入らない)。Windowsは将来OSアップデートでどうなるか分かったものではないのでパス。
    • Radeonのドライバ及びROCmが/optに20GB程度、その他ビルド用パッケージなどが/usrに30GBほど入るので、/を大きめに取る・/opt, /usrのパーティションを切るなど対策した方がいい。
  • メモリ: 32GB。Fooocusが画像サイズ1151x896で18GBくらい使っていたので、これくらいあった方がよさそう。なければスワップで乗り切る。
  • GPU: AMD Radeon RX570 8GB。1151x896だとVRAM 80%位使用する模様。

手順

ドライバインストール

ドライバ5.6や5.7で挑戦するならhttps://repo.radeon.com/amdgpu-installLink 以下からjammyのdebを選ぶ。6.xは大幅に変わると言われているので期待薄。再起動後rocminfoでRX570が表示されれば成功。
mkdir -p ~/stable_diffusion/rocm
cd ~/stable_diffusion/rocm
sudo usermod -aG video $USER
sudo usermod -aG render $USER
curl -O https://repo.radeon.com/amdgpu-install/5.5/ubuntu/jammy/amdgpu-install_5.5.50500-1_all.debLink 
sudo dpkg -i amdgpu-install_5.5.50500-1_all.deb
sudo amdgpu-install --usecase=graphics,rocm,hip,hiplibsdk --no-32
sudo reboot
rocminfo
rocm-smi

Pytorchのビルド

ビルドに必要なパッケージのインストール。
sudo apt install ¥
  git build-essential ¥
  python3-pip python3-venv python3-dev ¥
  libstdc++-12-dev libpng-dev libjpeg-dev
Python仮想環境とかdockerでやった方が失敗したときのやり直しがききやすい。
cd ~/stable_diffusion
python3 -m venv fooocus_env
source fooocus_env/bin/activate
pip install pygit2==1.12.2 packaging

Pytorch2のビルド。2.1は試してません。

  • 環境変数PYTORCH_ROCM_ARCHはrocminfoやrocm-smiで表示されるものから読み取る。複数指定できるがビルドに失敗しやすくなる。再度ビルドすると通ることもあるが、この後の動作確認が動かないとか経験したので欲張らず装着しているGPUだけに限定することがおすすめ。
curl -L -O https://github.com/pytorch/pytorch/releases/download/v2.0.1/pytorch-v2.0.1.tar.gzLink 
tar -xzvf pytorch-v2.0.1.tar.gz
cd pytorch-v2.0.1
echo 2.0.1 > version.txt
export CMAKE_PREFIX_PATH="$HOME/stable_diffusion/fooocus_env:/opt/rocm"
export USE_CUDA=0
# export PYTORCH_ROCM_ARCH="gfx803;gfx900;gfx906;gfx908;gfx90a;gfx1030"
export PYTORCH_ROCM_ARCH=gfx803
pip install cmake ninja
# sed -i '/^torch¥s*$/d' requirements.txt
pip install -r requirements.txt
pip install mkl mkl-include
python3 tools/amd_build/build_amd.py
python3 setup.py install

仮想環境入りなおして(import torchがエラーになる)、Pythonコマンドライン起動。

# envに入りなおさないと、import torchがエラーになる
deactivate
cd ~/stable_diffusion
source fooocus_env/bin/activate
python3
以下のコマンドで動作確認。最後のprint(res)でSegmentation faultが出る場合、PYTORCH_ROCM_ARCHの見直し(参考Link )、場合によってはUbuntu/Radeonドライバの入れ直し。
import torch
torch.cuda.is_available()  # True
torch.cuda.device_count()  # >=1 (装着しているGPU数による)
torch.cuda.current_device() # >=0 (装着しているGPU数による)
torch.cuda.get_device_name(torch.cuda.current_device()) # gfx803とかRX570を含む文字列

tensor = torch.randn(2, 2)
res = tensor.to(0)
print(res)
(Ctrl+D)

torchvisionのビルド・インストール

cd ~/stable_diffusion
source fooocus_env/bin/activate
curl -L -O https://github.com/pytorch/vision/archive/refs/tags/v0.15.2.tar.gzLink 
tar -xzvf v0.15.2.tar.gz
cd vision-0.15.2
echo 0.15.2 > version.txt
export CMAKE_PREFIX_PATH="$HOME/stable_diffusion/fooocus_env:/opt/rocm"
export FORCE_CUDA=1
python3 setup.py install
deactivate

Fooocusのインストール

Pytorchをビルドした仮想環境で実行。最後の--listenオプションは外のPCからアクセスできるようにするためなので、同じマシンのブラウザで動かすなら不要。
cd ~/stable_diffusion
source fooocus_env/bin/activate
git clone https://github.com/lllyasviel/Fooocus.gitLink 
cd Fooocus
python entry_with_update.py --listen

画像サイズ1152x896を作成するのにQualityで10-11分、Speedで6.5分弱。古いGPU故コア数少ない・BFloat16ない・Tensorエンジンもないので、これくらいになってしまうのか。ちょっと試してみたいとか打ち込む設定が決まっているならいいですが、いろいろ試すにはちょっと辛いかなぁ。

— posted by mu at 11:00 am   commentComment [0]  pingTrackBack [0]

RX570/Ubuntu 22.04でROCmを入れる

基本的には下記サイトの内容なのですが、言及されてないことも経験したので備忘録。[続き]Link

事前項目

PC

CPUはPCI atomicsをサポートしているものが必要。intelではHaswell (Core i 4000番台)以降、AMDは初代Ryzen以降。満たしてなくてもGPUドライバはインストールできるが、No GPU扱いになる。

No AMD GPUs specified #1742 (ROCm on GitHub)Link

Ubuntu

UbuntuはLTSを使用。20.4ならFocal Fossa、22.4はJammy Jellyfish(22.4.xではなく22.4)。上記サイトでも触れられているように、今のROCmはRX570をサポートしていないが事実として動くということを利用している。どのバージョンから動かなくなるのかわからないので、無闇に新しいものを使うのは避ける。

AMD GPUドライバは上記サイトで使われている5.5 or 5.6。おそらくLTSのカーネルバージョンじゃないと、ドライバビルド(下記amdgpu-installの部分)が失敗し入らない(22.4.3/カーネル6.2で経験)。うっかり新しいカーネルに更新しないようにする。

WikipediaのUbuntuバージョン履歴Link 。22.4はカーネル5.15がインストールできた。

22.4.xに古いカーネルを入れる場合、AMD GPUドライバインストール(amdgpu-install)前に新しいカーネルは全部削除する。でないと、ドライバインストーラはインストールされているすべてのカーネルバージョンに対してビルドを試み失敗、その後カーネルをアンインストールしようとするとまたドライバインストーラが動き出して失敗でアンインストールできなくなる。

手順

curl -O https://repo.radeon.com/amdgpu-install/5.5/ubuntu/jammy/amdgpu-install_5.5.50500-1_all.debLink  (https://repo.radeon.com/amdgpu-install/5.7/ubuntu/focal/amdgpu-install_5.7.50700-1_all.debLink  for Ubuntu 20.4 LTS)
sudo dpkg -i amdgpu-install_5.5.50500-1_all.deb
sudo amdgpu-install --usecase=rocm,mllib,mlsdk (or sudo amdgpu-install --usecase=graphics,rocm,mllib,mlsdk --no-32)
sudo usermod -aG video $USER
sudo usermod -aG render $USER
(Reboot Ubuntu)
sudo rocminfo
rocm-smi

現在CPU atomic未対応CPUのためrocminfo, rocm-smiともにGPUを認識しない状態。機材を調達して再挑戦の予定。

[2023/10/15] 訂正 --no-86 → --no-32

— posted by mu at 10:38 am   commentComment [0]  pingTrackBack [0]

WSL2でLinuxに固定IPを追加する

開発マシン上WSL2/Alpine/docker-composeでkafkaを動かそうとしたら手間取ったので、備忘録。

  • WSL2で動かすLinuxのIPアドレスはホストWindowsによってプライベートアドレスを与えられ、Windows起動の度に変わる(おそらくセキュリティ向上のため)
  • DHCPはLinux起動時にWSL2で特別な処理が行われているようで、/etc/network/interfaceに記載してもおそらく無視される
  • /etc/network/interfaceに書かれた内容はLinux起動後ifdown/ifupコマンドでstaticは反映されるが、DHCPはサーバーが見つからない理由でエラーになる
  • 上記DHCPが失敗した状態では、WSL2ホストマシン外と通信できない(Hyper-Vの仮想スイッチ設定をいじればできる?)
  • 一方dockerコンテナ上のkafkaは、ADVERTISED_HOST設定のため毎回変わるアドレスでは運用しづらい
Hyper-Vの仮想スイッチをいじると他のLinuxディストリビューションと併用する時に副作用が出そうなので、対象Linuxにプライベート固定アドレスを追加する方法を採る。アドレス例として
  • 192.168.99.1: WSL2ホスト側のアドレス(=Windows)
  • 192.168.99.100: Windowsから見たLinux側のアドレス

Windows側

仮想スイッチ'vEthernet (WSL)'はWSL2起動時に作成されるようなので、先にLinuxディストリビューションを起動しておく。このスイッチにホストWindowsのアドレスを追加。要管理者権限。Windows再起動ごとに行う。
 netsh interface ip add address "vEthernet (WSL)" 192.168.99.1 255.255.255.0

Linux側(dockerホスト on WSL2)

Linuxに固定アドレスを与える。要root。こちらもLinux起動ごとに必要。
ip addr add 192.168.99.100/24 dev eth0

Linux側(docker-compose)

wurstmeister/kafka-dockerLink を使用。docker-compose.yml変更点は
  • kafkaのportsを9092:9092に
  • KAFKA_ADVERTISED_HOST_NAMEを書き換え

docker-compose後はホストWindowsからはbootstrap-server=192.168.99.100:9092でkafkaにアクセス可能。

version: '2'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
    restart: unless-stopped

  kafka:
    build: .
    ports:
      - "9092:9092"
    environment:
      DOCKER_API_VERSION: 1.22
      KAFKA_ADVERTISED_HOST_NAME: 192.168.99.100
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

[参考]

— posted by mu at 07:53 pm   commentComment [0]  pingTrackBack [0]

Pythonでnumpy.ctypes.data_as()→C側でAccess violation

YOLOLink リポジトリに含まれるdarknet_images.pyに複数画像一括処理を行うbatch_detectionという関数があるのですが、2枚以上の画像を処理させようとするとC側関数実行中にOSError/access violation例外が発生。1枚(要素数1の配列を渡す)は正常に処理されることから、ポインタの渡し間違いという類ではなさそう。

結論

import numpy as np
from ctypes import *

def makeArray():
    arr = numpyの配列を作る
    return arr.ctypes.data_as(ctypes.POINTER(ctypes.c_float))


c_func(makeArray())

みたいに関数でnumpy配列作ってctypesのポインタだけを返している場合、arrのサイスが大きいと関数抜けた時点でarrがガベージコレクションされてしまい、data_as()で得たアドレスはc_funcが呼ばれる前に無効になる可能性がある。

今回のYOLOの件は画像1枚だとたまたまガベコレされなかっただけで、本質的には危険なのでしょう。具体的にはdarknet_images.pyのprepare_batch()関数でbatch_arrayがガベコレされてしまいます。手っ取り早い解決としては、同ファイル内で
  • prepare_batch()の返値にbatch_arrayを含めるようにし、呼び出す側のbatch_detection()はC関数darknet.network_predict_batch()を呼び終えるまでbatch_arrayを保持する
  • prepare_batch()とbatch_detection()を一つの関数にまとめ、batch_arrayがガベコレされないようにする

でしょうか。前者はコード的にあまり美しくなさそうですが。

私と同じ問題にあたる人は稀でしょうが、本質的な理由はWindows/Linux関係なく起こりそう。ctypesのいい勉強になりました。

[参考]

— posted by mu at 07:18 pm   commentComment [0]  pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0132 sec.
prev
2024.4
next
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30