itsource

Python에서 메모리를 명시적으로 해방하려면 어떻게 해야 합니까?

mycopycode 2022. 9. 21. 00:03
반응형

Python에서 메모리를 명시적으로 해방하려면 어떻게 해야 합니까?

저는 큰 입력 파일에 동작하는 파이썬 프로그램을 작성하여 삼각형을 나타내는 몇 백만 개의 객체를 만들었습니다.알고리즘은 다음과 같습니다.

  1. 입력 파일을 읽다
  2. 파일을 처리하여 꼭지점으로 표시되는 삼각형의 목록을 작성합니다.
  3. 정점을 OFF 형식으로 출력합니다. 정점 목록 뒤에 삼각형 목록이 나옵니다.삼각형은 정점 목록으로 인덱스로 표시됩니다.

OFF의 경우 삼각형을 인쇄하기 전에 꼭지점 전체 목록을 인쇄해야 합니다. 즉, 출력을 파일에 쓰기 전에 삼각형의 목록을 메모리에 보관해야 합니다.한편, 리스트의 사이즈 때문에 메모리 에러가 발생하고 있습니다.

Python에게 데이터 중 일부가 더 이상 필요하지 않으며 데이터를 해방할 수 있다고 말하는 가장 좋은 방법은 무엇입니까?

Python Official Documentation에 따르면, Garbage Collector를 명시적으로 호출하여 참조되지 않은 메모리를 해방할 수 있습니다.gc.collect() §:

import gc

gc.collect()

를 하고 .del:

del my_array
del my_object
gc.collect()

불행히도 (사용하는 Python의 버전 및 릴리스에 따라) 일부 유형의 개체는 "자유 목록"을 사용합니다. 이는 깔끔한 로컬 최적화이지만 메모리 조각화를 일으킬 수 있습니다. 특히, 특정 유형의 개체에만 더 많은 메모리가 할당되어 있으므로 "일반 기금"에서 사용할 수 없습니다.

메모리를 일시적으로 대량으로 사용하는 것이 완료되었을 때 모든 자원을 시스템으로 되돌리는 확실한 유일한 방법은 서브프로세스로 사용하는 것입니다.서브프로세스에서는 메모리를 많이 사용하는 작업이 종료됩니다.이러한 상황에서 운영체제는 제 역할을 수행하며 하위 프로세스가 소비했을 수 있는 모든 리소스를 기꺼이 재활용합니다. 大 fortun는multiprocessing은 최신 Python.module에서 에는 다소을 않게 .

사용 예에서는 서브프로세스가 결과를 축적하여 메인프로세스에서 그 결과를 확실하게 이용할 수 있도록 하는 최선의 방법은 반임시 파일(반임시 파일)을 사용하는 것입니다.즉, 닫았을 때 자동으로 삭제되는 파일 종류가 아니라 t를 모두 끝냈을 때 명시적으로 삭제하는 일반 파일입니다.헴)

del스테이트먼트는 도움이 될 수 있지만 IIRC에서는 메모리를 해방할 없습니다.박사님은 여기 계시고...공개되지 않은지는 여기 계시죠?

Linux와 Unix 타입의 시스템에 있는 사람들이 파이썬 프로세스를 포킹하여 작업을 수행하고 결과를 얻은 후 종료하는 것을 들은 적이 있습니다.

이 기사에는 Python 가비지 컬렉터에 대한 메모가 있지만 메모리 제어 부족이 관리 메모리의 단점이라고 생각합니다.

Python은 가비지 컬렉션이므로 목록 크기를 줄이면 메모리가 회수됩니다."del" 문을 사용하여 변수를 완전히 제거할 수도 있습니다.

biglist = [blah,blah,blah]
#...
del biglist

)del는 오브젝트에 대한 다른 참조가 없는 경우 삭제 가능한 것으로 표시되므로 친구가 될 수 있습니다.현재 대부분의 경우 CPython 인터프리터는 나중에 사용하기 위해 이 메모리를 보관하고 있기 때문에 운영체제는 "자유" 메모리를 인식하지 못할 수 있습니다.)

데이터에 대해 보다 콤팩트한 구조를 사용한다면 애초에 메모리 문제가 발생하지 않을 수 있습니다.숫자 .array " " " " " "numpy you. 배열에 할 수 .NumPy 3xN 배열에 정점을 넣고 N-element 배열에 삼각형을 배치하면 메모리를 절약할 수 있습니다.

명시적으로 메모리를 해방할 수 없습니다.필요한 것은 오브젝트에 대한 참조를 유지하지 않도록 하는 것입니다.그런 다음 가비지가 수집되어 메모리가 해방됩니다.

이 경우 대용량 목록이 필요한 경우 일반적으로 생성기/반복기를 사용하여 코드를 재구성해야 합니다.이렇게 하면 대용량 목록을 메모리에 저장할 필요가 전혀 없습니다.

나도 파일에서 그래프를 읽을 때 비슷한 문제가 있었다.이 처리에는 메모리에 맞지 않는 200 000 x 200 000 플로트 매트릭스(한 번에 한 줄씩)의 계산이 포함되어 있습니다..gc.collect()메모리 관련 문제는 해결되었지만 성능 문제가 발생했습니다.수 된 메모리의 일정하게 , 에의 대해서 행해지고 .gc.collect()아까보다 시간이 좀 더 걸렸어요.그래서 쓰레기 수집은 계산 시간의 대부분을 소비했습니다.

메모리와 퍼포먼스의 문제를 해결하기 위해서, 한번 읽은 적이 있는 멀티 스레드 트릭으로 전환했습니다(죄송합니다만, 관련 투고를 찾을 수 없습니다.내가 파일의 한 줄을 크게 읽기 전에for및, "" " " " "gc.collect()메모리의 빈 공간을 확보할 수 있습니다.이제 새 스레드에서 파일 청크를 읽고 처리하는 함수를 호출합니다.스레드가 종료되면 메모리는 이상한 성능 문제 없이 자동으로 해방됩니다.

실제로는 다음과 같이 동작합니다.

from dask import delayed  # this module wraps the multithreading
def f(storage, index, chunk_size):  # the processing function
    # read the chunk of size chunk_size starting at index in the file
    # process it using data in storage if needed
    # append data needed for further computations  to storage 
    return storage

partial_result = delayed([])  # put into the delayed() the constructor for your data structure
# I personally use "delayed(nx.Graph())" since I am creating a networkx Graph
chunk_size = 100  # ideally you want this as big as possible while still enabling the computations to fit in memory
for index in range(0, len(file), chunk_size):
    # we indicates to dask that we will want to apply f to the parameters partial_result, index, chunk_size
    partial_result = delayed(f)(partial_result, index, chunk_size)

    # no computations are done yet !
    # dask will spawn a thread to run f(partial_result, index, chunk_size) once we call partial_result.compute()
    # passing the previous "partial_result" variable in the parameters assures a chunk will only be processed after the previous one is done
    # it also allows you to use the results of the processing of the previous chunks in the file if needed

# this launches all the computations
result = partial_result.compute()

# one thread is spawned for each "delayed" one at a time to compute its result
# dask then closes the tread, which solves the memory freeing issue
# the strange performance issue with gc.collect() is also avoided

Python 인터프리터를 「축소」해 메모리를 해방할 수 있는(또는 메모리 문제를 회피할 수 있는) 방법을 게재하고 있는 사람도 있습니다.그들의 아이디어를 먼저 시험해 보는 것이 좋을 것 같다.하지만 당신의 질문에 직접 대답하는 것이 중요하다고 생각합니다.

Python에게 메모리를 해방하라고 직접 말할 수 있는 방법은 없습니다.사실 그렇게 낮은 수준의 제어를 원한다면 확장자를 C 또는 C++로 써야 합니다.

단, 여기에는 도움이 되는 툴이 몇 가지 있습니다.

에서 이미 언급했듯이 코드 Python 코드)에서 더 이상 않을 수 .gc.collect()특히 장기간에 걸친 프로그램에서는 아무것도 해방되지 않습니다.를 하고 있는 는, 함수 「Linux」를 할 수 .malloc_trim(man 페이지).예를 들어 다음과 같습니다.

import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.malloc_trim(0)

정점 재사용에 관심이 없는 경우 두 개의 출력 파일(정점용과 삼각형용)을 사용할 수 있습니다.그런 다음 작업이 완료되면 삼각형 파일을 정점 파일에 추가합니다.

언급URL : https://stackoverflow.com/questions/1316767/how-can-i-explicitly-free-memory-in-python

반응형