1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

4BでmultiprocessingのManagerを使って、ndarrayを共有する

Last updated at Posted at 2024-01-14

Windowsの再インストールというトラブルに合い、現在Pythonはラズベリーパイだけでやっています。ただコードはWindows10のメモ帳で書いています。WinSCPでラズベリーパイへファイル転送し、VNCviewerでラズベリーパイ上のThonnyを起動しています(ラズベリーパイは小モニターを付けて、棚の上に置いています)。WinSCP・VNCviewerは、IPアドレス入力だけでつながります。暗号化・認証でもエラーは出たことがありません。ラズベリーパイOSのBuster・Bookwormと大変相性がいいです。ラズベリーパイのPythonコードを作成する上で、'三種の神器'です。

開発環境の話が少し長くなりましたが、今回はラズベリーパイ4B上で、OSのbookwormとbusterを使いました。タイトルにあるPythonのMultiprocessingのManegerのメモリー共有は、「① 前設定が簡単である」、「② listが使える」という利点があります。ただManagerは「処理速度が少し遅い」という欠点があります。またmultiprocessingのメモリー共有には、Manager以外にctypesも含め多くの高速な方法があります。しかし今回は、Managerが「① 前設定が簡単」であることに着目しました。というより初心者なので、他の方法は少し難解でした。そしてndarrayを共有する上で、「② listが使える」ことも魅力でした。

コードは、最初にcore1で、4個の画像ファイルを読み込みndarrayとします。さらに同じcore1で、画像ndarrayを「Managerのlist」に書き込みます。次にcore4で、この「Managerのlist」を読み出し、画像ndarrayに戻します。最後に同じcore4で、画像ndarrayをディスプレイに表示します。これのループです。

またコード作成の途上で意外だったのは、「Managerのlist」の「読み出しエラー」が多いことです。ファンを回して冷却すると、エラー率は少し下がります。しかしファンで冷却しても、「読み出しエラー」はまだ残ります。今まで、「pythonの標準のlist」操作でエラーは無かったので意外でした。ほとんどの部分が、「Managerのlist」の「読み出しエラー」のクリアです。以下がコードです。

# manager-ndarray---bookworm-buster.py
import time
from multiprocessing import Manager, Value, Process
import numpy as np
import cv2 as cv


# Raspberry Pi 4B, 8G   under cooling   on Thonny
# ------------------------------------------------
# Buster(x32) OS:  Linux raspberrypi 5.10.103-v7l+ #1529 SMP Tue Mar 8 12:24:00 GMT 2022 armv7l GNU/Linux
# Python 3.7.3 (default, Oct 31 2022, 14:04:00)
# numpy  1.20.1
# OpenCV 3.4.15.55
# ------------------------------------------------
# Bookworm(x64) OS:  Linux raspberrypi 6.1.0-rpi7-rpi-v8 #1 SMP PREEMPT Debian 1:6.1.63-1+rpt1 (2023-11-24) aarch64 GNU/Linux
# Python 3.11.2 (main, Mar 13 2023, 12:18:29)
# numpy  1.24.2
# OpenCV  4.6.0  (sudo apt install python3-opencv)
# ------------------------------------------------


def process1(vcount00, f_plist0, plist0):

    img00 = cv.imread("d00.png")   #640w x 480h
    img01 = cv.imread("d01.png")
    img02 = cv.imread("d02.png")
    img03 = cv.imread("d03.png")   #warning for bookworm

    height00 = 480
    width00  = 640
    rgb00    =   3

    try:
        while(True):
            count00_old = vcount00.value
            q,  mod = divmod(count00_old, 4)
            if   mod  == 0:
                img480 = img00.copy()
            elif mod == 1:
                img480 = img01.copy()
            elif mod == 2:
                img480 = img02.copy()
            elif mod == 3:
                img480 = img03.copy()

            ## preWriting 3D-->4D
            #print(repr(img480))
            img480_4d  = np.reshape(img480, [1, height00, width00, rgb00])
            #print(repr(img480_4d))
            
            ## Writing to plist0
            while True:
                time.sleep(0.0001)
                if f_plist0.value == 0:
                    f_plist0.value = 9
                if f_plist0.value == 9 or f_plist0.value == 1:
                    f_plist0.value = 1
                    break
            plist0[:]= []
            for i in img480_4d:
                plist0.append(i)
            if len(plist0)==0:
                print("plist0==0") #### No error
            f_plist0.value = 9
            vcount00.value  += 1
            time.sleep(0.5)

    except KeyboardInterrupt:
        print('process1  excepted')


def process4(vcount00, f_plist0, plist0):

    img = cv.imread("Init.png")   #warning for bookworm
    cv.imshow("Image1", img)
    key = cv.waitKey(1000)

    height00 = 480 
    width00  = 640
    rgb00   =   3

    # a_ndarray00c  = np.reshape(img, [1, height00, width00, rgb00])

    count0_old=0
    try:
        while(True):
            l_ndarray00=[]
            time.sleep(0.001)
            if count0_old < vcount00.value :
                count0_old = vcount00.value

                ## Reading from plist0
                i_retry = 0
                while True: 

                    while True:
                        time.sleep(0.0001)
                        if f_plist0.value == 9:    
                            f_plist0.value = 4
                            break
                    for i in plist0:
                        l_ndarray00.append(i)
                    f_plist0.value = 9

                    # double 'while' loop for read-error
                    i_retry += 1
                    if i_retry >= 20:
                        print("i_retry >= 20  error")
                        break
                    if len(l_ndarray00) == 0:
                        time.sleep(0.0001)
                        continue
                    else:
                        print(i_retry)    #### sometimes out of 1
                        a_ndarray00 = np.array(l_ndarray00, dtype="uint8")
                        a_ndarray00c = a_ndarray00.copy()
                        break

                # 4D-->3D
                a_ndarray00c333  = np.reshape(a_ndarray00c, [height00, width00, rgb00])
                img480 = cv.resize(a_ndarray00c333, (width00, height00))

                ##  imshow
                cv.imshow("Image1", img480)
                key = cv.waitKey(10)

    except KeyboardInterrupt:
        cv.destroyAllWindows()
        print('process4  excepted')


if __name__ == "__main__":

    with Manager() as manager:

        vcount00 = manager.Value('i', 0)
        vcount00.value  = 0

        f_plist0 = manager.Value('i', 0)
        f_plist0.value  = 1

        plist0  =  manager.list()

        process1 = Process(target=process1, args=[vcount00, f_plist0, plist0])
        process4 = Process(target=process4, args=[vcount00, f_plist0, plist0])

        process1.start()
        process4.start()

        process1.join()
        process4.join()

動かしてみて、bookworm(x64)とBuster(x32)は、ほぼ同じ動作でした。ただ画面操作などをすると、時々1以外が出ます。割り込みが、同じcoreを使っているのかもしれません。動作上は、今回のシンプルなエラー回避策により、「Managerのlist」で、共有できることがわかりました。

お忙しい中、ご覧いただきありがとうございました。
なお公開プログラムは、コピー・改変も自由です。著作権に関する問題も発生しません。

本ページは、Pythonのmultiprocessing 等を参考にしています。
https://docs.python.org/ja/3.7/library/multiprocessing.html
https://numpy.org/doc/1.16/reference/generated/numpy.array.html
https://numpy.org/doc/1.16/reference/generated/numpy.reshape.html

以下はプログラム中で使用した画像です。
Init.png
Init.png
d00.png
d00.png
d01.png
d01.png
d02.png
d02.png
d03.png
d03.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?