스택큐힙리스트

파이썬 멀티프로세싱 PicklingError: <type 'function'>을(를) 피클링 할 수 없습니다. 본문

카테고리 없음

파이썬 멀티프로세싱 PicklingError: <type 'function'>을(를) 피클링 할 수 없습니다.

스택큐힙리스트 2023. 4. 22. 03:25
반응형

간단한 예시로 오류를 재현할 수 없어서 죄송합니다. 또한, 제 코드는 너무 복잡해서 게시할 수 없습니다. 그러나 일반 Python 대신 IPython 셸에서 프로그램을 실행하면 잘 작동합니다.

나는 이 문제에 대한 이전 노트를 확인해 보았다. 그들은 모두 클래스 함수 내에서 정의된 함수를 호출하기 위해 pool을 사용함으로써 발생했다. 그러나 나는 이와 같은 경우가 아니다.

Exception in thread Thread-3:

Traceback (most recent call last):

File /usr/lib64/python2.7/threading.py, line 552, in __bootstrap_inner

self.run()

File /usr/lib64/python2.7/threading.py, line 505, in run

self.__target(*self.__args, **self.__kwargs)

File /usr/lib64/python2.7/multiprocessing/pool.py, line 313, in _handle_tasks

put(task)

PicklingError: Can't pickle : attribute lookup __builtin__.function failed

어떤 도움이라도 감사히 받겠습니다.

업데이트 : 내가 피클링 한 함수는 모듈의 최상위 레벨에서 정의되어 있습니다. 그러나 중첩 함수를 포함하는 함수를 호출합니다. 즉, #f() ,가 @#g() 를 호출하고 @#g() 이 중첩 함수 i() , 를 가진 h()를 호출하며 나는 pool.apply_async(f) . 를 호출하고 있습니다. #f() , , @#g() , h()는 모두 최상위 레벨에서 정의되어 있습니다. 이 패턴을 사용한 더 간단한 예제를 시도해 보았고 작동했습니다.

답변 1

여기 list of what can be pickled 가 있습니다. 특히, 함수는 모듈의 최상위 레벨에서 정의된 경우에만 pickleable합니다.

이 코드 부분:

import multiprocessing as mp

class Foo():

@staticmethod

def work(self):

pass

if __name__ == '__main__':

pool = mp.Pool()

foo = Foo()

pool.apply_async(foo.work)

pool.close()

pool.join()

당신이 게시한 것과 거의 동일한 오류가 발생합니다.

Exception in thread Thread-2:

Traceback (most recent call last):

File /usr/lib/python2.7/threading.py, line 552, in __bootstrap_inner

self.run()

File /usr/lib/python2.7/threading.py, line 505, in run

self.__target(*self.__args, **self.__kwargs)

File /usr/lib/python2.7/multiprocessing/pool.py, line 315, in _handle_tasks

put(task)

PicklingError: Can't pickle : attribute lookup __builtin__.function failed

문제는 모든 메서드가 작업을 워커 프로세스에 전달하기 위해 mp.SimpleQueue를 사용한다는 것입니다. mp.SimpleQueue를 통과하는 모든 것은 pickable해야하며 foo.work는 모듈의 최상위 수준에서 정의되지 않았기 때문에 pickable하지 않습니다.

foo.work()을 호출하는 최상위 함수를 정의함으로써 고칠 수 있습니다.

def work(foo):

foo.work()

pool.apply_async(work,args=(foo,))

foo 이 선택 가능하다는 것에 주목하세요. 왜냐하면 Foo 가 최상위 수준에서 정의되었고 foo.__dict__ 가 선택 가능하기 때문입니다.

답변 2

Python Multiprocessing PicklingError: 'function' 자료형은 피클링할 수 없습니다

파이썬에서, 멀티프로세싱은 CPU 인텔코어, AMD 등에서 작업을 병렬로 수행할 수 있도록 해주는 방법이다. 이 기술은 데이터 과학, 머신러닝, 인공지능 분야에서 매우 중요하다. 그러나 멀티프로세싱을 사용하려고 할 때 PicklingError: Can't pickle 과 같은 오류가 발생하는 경우가 종종 있다.

이 오류는 function 자료형이 피클링될 수 없다는 것을 의미한다. Pickling은 객체를 저장하거나 전송할 수 있도록 바이트 스트림으로 변환하는 과정을 말한다. Pickle은 일종의 시리얼라이제이션 방법으로, 객체의 메모리 상태를 바이트 스트림으로 변환해주는 것이다. 이 프로세스에서, 함수 객체를 피클링할 때 발생하는 문제 때문에 종종 이 오류가 발생한다.

함수 객체는 파이썬에서 일급 함수(first-class function)로 간주되며, 함수의 인자로 전달하거나 반환 값으로 사용할 수 있다. 함수 객체는 코드 객체와 스코프 객체를 포함하고 있으므로, 피클링하려는 경우에 코드 객체와 스코프 객체 모두가 직렬화되어야 한다. 그러나 이러한 객체들은 너무 복잡하고, 피클링할 수 없는 내부적인 참조를 가지고 있기 때문에 피클링할 수 없는 것이다.

따라서, 멀티프로세싱을 사용할 때 함수 객체를 피클링할 수 없다는 경고 메시지를 확인하면, 다음과 같은 대안이 있다. 첫 번째로는 함수를 분리하고, 인자로 전달하는 것이다. 두 번째로는 함수 객체 자체를 사용하는 대신 객체 이어지는 메소드를 사용하는 것이다. 마지막으로는 클래스를 정의하고, 클래스의 인스턴스를 만들어서 함수 객체를 사용하는 것이다.

이러한 대안 중 어떤 방법을 선택할지는 상황에 따라 다를 것이다. 함수 객체를 피클링할 수 없다면, 위와 같은 대안을 사용하여 프로그램을 수정하고, 멀티프로세싱에 대한 성능 향상을 이끌어낼 수 있다.

반응형
Comments