Multi-Processing-python

채마노마노·2021년 4월 27일
0

Python

목록 보기
1/1

파이썬(Python) Multiprocessing - Pool

멀티 프로세싱을 활용하면 복잡하고 시간이 걸리는 작업을 별도의 프로세스를 생성 후 병렬처리해서
보다 빠른 응답처리 속도를 기대할 수 있는 장점이 있습니다.

최근들어 대용량의 빅데이터의 분석 및 예측 등의 머신러닝을 지원하는 다양한 패키지에서 대부분 멀티 프로세싱을 활용해서 멀티코어의 CPU의 장점을 극대화하고 빠른 처리를 지원하고 있습니다.

다만, 충분한 사전 지식 및 병렬 프로그래밍의 이해 없이 코드를 작성한다면, 싱글 프로세스의 응답속도보다 시간이 지연되고 별도로 예상치 못한 결과가 나타날 수 있으니 프로세스 및 쓰레드 등의 지식이 중요합니다.

또한, 멀티프로세싱은 오버헤드의 증가 및 메모리 사용률이 높아지는 단점도 존재합니다

파이썬(Python) MultiProcessing - 구조

보통 Multiprocessing 실행 흐름은 아래와 같이 나타낼 수 있으며, 관련 예제는 하단에서 설명합니다.

출처 : https://sebastianraschka.com/Articles/2014_multiprocessing.html

밑의 코드는 각각의 이미지들을 crop하고 저장하는것을 multiprocessing으로 구현했습니다. 서버에서는 cpu코어가 많아서 20~30로 줬었는데 process가 진행하다가 디렉토리에서 다른 디렉토리로 넘어갈 때 멈추는 현상이 있었습니다. python 정책에 의해서 인지 다른 프로세스가 끝나서 그런지 아니면 서버에서 다른 작업을 진행하느라 그것을 기다리느라 오래 걸린 것인지(프로세스의 경우 우선 순위에 따라서 진행되는걸로 알고 있습니다.) 정확한 이유는 알 수 없습니다. 추후 이 부분에 대해서는 추가로 작성하는걸로....(이걸로 대략 3.5TB의 이미지를 처리 했었다.)









import cv2
import glob
import json
import os
import numpy as np
import os
from tqdm import tqdm
import multiprocessing
import pickle
import logging

logger = logging.getLogger('__name__')
fileHandler = logging.FileHandler('preprocessing.log')
formatter = logging.Formatter("%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] - %(message)s")
logger.addHandler(fileHandler)
logger.setLevel(level=logging.DEBUG)

Obj_list = ['AirwalkMachine', 'BasketballStand', 'Bench', 'BenchBack', 'BicycleRack', 'Bollard',
            'BoundaryStone', 'BrailleBlock', 'ConstructionCover', 'DirectionalSign', 'DringkingFountain', 'FlowerStand',
            'GoalPost', 'HandicapZone', 'Manhole', 'MovableToilet', 'Pagora', 'PavementBlock',
            'PostBox', 'ProtectionFence', 'PublicToilet', 'RoadSafetySign', 'RunningMachine', 'Seesaw', 'ShadeCanopy',
            'SignalController', 'SignalPole', 'SitupMachine', 'Slide', 'SoundproofWalls', 'StationShelter',
            'StationSign', 'StreetTreeCover', 'StreetLampPole', 'SubwayVentilation', 'Swing', 'TelephoneBooth',
            'TrashCan', 'TreeSupport','Trench', 'TurnMachine', 'WalkAcrossPreventionFacility', 'Elevator']

Obj_status = ['Normal', 'Repair', 'Substitution_Disposal']


''' 이미지 resize 및 json 파일 저장, crop 이미지 저장 '''
// logging.warn("warn로그입니다.")
// with open('/data2/task42/img_list.pickle', 'rb') as fr:
//     imgfile_list = pickle.load(fr)
class_list = ['기타시설물', '녹지시설물', '도시시설물', '보호시설물', '서비스시설물', '운동시설물', '위생시설물', '통행시설물', '휴게시설물']

for a in range(len(class_list)):
    class_list_path = f'/mnt/data3/AI_data/facility/facility/{class_list[a]}'  # path 수정
    obj_list = os.listdir(class_list_path)  # list, 시설물 클래스가 담겨있는 리스트
    for b in range(len(obj_list)):
        obj_list_path = f'/mnt/data3/AI_data/facility/facility/{class_list[a]}/{obj_list[b]}'
        status_list = os.listdir(obj_list_path)
        for c in range(len(status_list)):
            if status_list[c] in ["교체폐기", "수리", "정상"]:
                imgfile_list = glob.glob(f'/mnt/data3/AI_data/facility/facility/{class_list[a]}/{obj_list[b]}/{status_list[c]}/*.jpeg')
                jsonfile_list = glob.glob(f'/mnt/data3/AI_data/facility/facility/{class_list[a]}/{obj_list[b]}/{status_list[c]}/*.json')

                data_length = len(imgfile_list)

                def img_crop(i):
                    try:
                        filename = jsonfile_list[i]
                        name = filename.split('/')[-1]
                        name = name.replace('.json', '')
                        print('filename : ', filename)

                        # img_name = name.replace('.json','.jpg')

                        # print('name : ', name)
                        # print('img_name : ', img_name)

                        with open(filename) as data:
                            json_data = json.load(data)  # json 파일 읽어옴

                            if 'unableReason' not in list(json_data.keys()):
                                objs = json_data['annotations']
                                for i, obj in enumerate(objs):
                                    id = obj["parent_id"]

                                    bbox = obj['bbox']

                                    d_num = 0
                                    try:
                                        status = obj['attributes']['status']

                                        print(status)

                                        task42_class = obj['attributes']['class']

                                        if status == 'Normal':
                                            os.makedirs(os.path.join(f'/mnt/data2/task42/cropped_train/', 'images',f'{task42_class}', f'{status}'),exist_ok=True)

                                            bbox = obj['bbox']
                                            x = bbox[0]
                                            y = bbox[1]
                                            w = bbox[2]
                                            h = bbox[3]

                                            img = cv2.imread(imgfile_list[i], cv2.IMREAD_COLOR)
                                            # print('Normal_img : ',img)
                                            # print(root)

                                            img_crop = img[int(y):int(y + h), int(x):int(x + w)]

                                            # os.walk('절대경로').next()[2] == > 디렉토리내의 파일개수

                                            cv2.imwrite(os.path.join('/mnt/data2/task42/cropped_train', 'images',obj['attributes']['class'], 'Normal',f'{name}+{i}.jpg'), img_crop)

                                        elif status == 'Repair':
                                            os.makedirs(os.path.join('/mnt/data2/task42/cropped_train', 'images',f'{task42_class}', f'{status}'),exist_ok=True)

                                            for j in range(1, len(objs)):
                                                if i + j > len(objs) - 1:
                                                    break
                                                elif (objs[i + j]["parent_id"] != 0 and objs[i + j]["category_id"] == 2):
                                                    d_num += 1
                                            if d_num != 0 and obj["category_id"] == 1:
                                                bbox = obj['bbox']
                                                x = bbox[0]
                                                y = bbox[1]
                                                w = bbox[2]
                                                h = bbox[3]

                                                img = cv2.imread(imgfile_list[i], cv2.IMREAD_COLOR)


                                                img_crop = img[int(y):int(y + h), int(x):int(x + w)]
                                                # os.walk('절대경로').next()[2] == > 디렉토리내의 파일개수

                                                cv2.imwrite(os.path.join('/mnt/data2/task42/cropped_train', 'images',obj['attributes']['class'], 'Repair',f'{name}+{i}+{d_num}.jpg'), img_crop)

                                        else:
                                            os.makedirs(os.path.join('/mnt/data2/task42/cropped_train', 'images',f'{task42_class}', 'Substitution_Disposal'),exist_ok=True)

                                            for j in range(1, len(objs)):
                                                print("Substitution_Disposal_j : ", j)
                                                if i + j > len(objs) - 1:
                                                    break
                                                elif (objs[i + j]["parent_id"] != 0 and objs[i + j][
                                                    "category_id"] == 2):
                                                    d_num += 1
                                            print("Substitution_Disposal_d_num: ", d_num)
                                            if d_num != 0 and obj["category_id"] == 1:
                                                bbox = obj['bbox']
                                                x = bbox[0]
                                                y = bbox[1]
                                                w = bbox[2]
                                                h = bbox[3]

                                                img = cv2.imread(imgfile_list[i], cv2.IMREAD_COLOR)


                                                img_crop = img[int(y):int(y + h), int(x):int(x + w)]

                                                cv2.imwrite(os.path.join('/mnt/data2/task42/cropped_train', 'images',
                                                                         obj['attributes']['class'] + '_Substitution_Disposal',f'{name}+{i}+{d_num}.jpg'), img_crop)
                                                print("\n", obj["category_id"], " - ", d_num, " - ", name, " - ",
                                                      obj["attributes"]["class"], " crop saved")
                                    except:
                                        pass


                    except:
                        pass


                if __name__ == '__main__':
                    if 1:
                        pool = multiprocessing.Pool(processes=6)
                        pool.map(img_crop,  range(0,len(imgfile_list)))
                        

0개의 댓글