파이썬에서의 메모리 관리: 파괴적 vs. 비파괴적 연산 이해하기

소환인·2023년 10월 28일
0

스터디노트

목록 보기
12/48

1. sort vs. sorted

파이썬에서는 리스트의 정렬에 두 가지 주요 방법이 있습니다: sort() 메서드와 sorted() 함수.

  • list.sort():

    • 리스트 객체의 메서드로, 원본 리스트 자체를 정렬합니다.

    • 원본데이터가 보존되지 않고 변경됩니다. 파괴적 프로그래밍 방식입니다.

    • 반환 값은 None입니다. (즉, 원본 리스트가 직접 변경됩니다.)

      numbers = [3, 1, 2]
      numbers.sort()
      print(numbers)  # [1, 2, 3]
  • sorted():

    • 내장 함수로, 정렬된 새로운 리스트를 반환합니다.

    • 원본 리스트는 변경되지 않습니다.

    • 비파괴적 프로그래밍 방식입니다.

      numbers = [3, 1, 2]
      sorted_numbers = sorted(numbers)
      print(numbers)        # [3, 1, 2]
      print(sorted_numbers) # [1, 2, 3]

2. 파괴적 vs. 비파괴적

"파괴적"과 "비파괴적"은 데이터나 객체의 변경 방식에 관한 프로그래밍 용어입니다.

  • 파괴적 (In-place 또는 Destructive):

    • 원본 데이터나 객체 자체를 수정합니다.
    • 파괴적 연산을 수행한 후에는 원본 데이터를 복구할 수 없습니다.
    • 메모리를 추가로 사용하지 않거나 적게 사용하는 경우가 많습니다.
    • 예: 파이썬 리스트의 sort() 메서드, 판다스의 inplace=True 옵션 등.
  • 비파괴적 (Non-destructive):

    • 원본 데이터나 객체를 변경하지 않고, 변경된 새로운 데이터나 객체를 생성해서 반환합니다.
    • 원본 데이터는 그대로 유지되므로 연산 후에도 원본 데이터에 접근할 수 있습니다.
    • 원본 데이터, 원본 객체에 대해 새로운 데이터나 객체를 생성하기에 메모리를 추가로 사용할 수 있습니다.
    • 예: 파이썬의 sorted() 함수, 대부분의 판다스 메서드에서 inplace=False 일 때의 동작 등.

데이터나 객체를 수정할 때는 파괴적, 비파괴적 방식 중 어느 것이 더 적절한지를 잘 판단해야 합니다. 선택은 연산의 목적, 메모리 사용량, 원본 데이터의 보존 여부 등 여러 요인을 고려하여 이루어져야 합니다.

3. 판다스에서 inplace=True 옵션의 사용

판다스의 DataFrame과 Series에서 데이터 조작을 수행할 때, inplace 파라미터는 자주 사용되는 옵션 중 하나입니다. 판다스의 DataFrame을 조작할 때 inplace=True 옵션은 파괴적 방식을 나타냅니다.

  • inplace=True:

    • inplace=True를 설정하면, 해당 연산은 원본 DataFrame 또는 Series에 직접 반영됩니다.
    • 이 방식은 원본 데이터에 대한 변경이 필요할 때 유용합니다.
    • 반환 값은 None입니다. 따라서 연산의 결과를 다른 변수에 할당하려고 하면 아무것도 저장되지 않게 됩니다.
    • 주피터 노트북에서 inplace=True 옵션을 사용하면 반환 값이 None이기에 "Output"에 따로 결과가 표시되지 않습니다.
    import pandas as pd
    df = pd.DataFrame({'A': [1, 2, 3]})
    df.drop('A', axis=1, inplace=True)
  • inplace=False 또는 기본값:

    • 대체로 inplace 옵션의 기본값은 False입니다.
    • inplace=False는 원본 DataFrame 또는 Series에는 아무런 영향을 주지 않습니다.
    • 연산의 결과로 새로운 DataFrame 또는 Series 객체를 반환합니다.
    • 이 방식은 원본 데이터를 유지하면서 변경 사항을 볼 때나 다른 변수에 저장할 때 유용합니다.
    • 연산 결과 새로운 객체를 반환하기에 주피터 노트북에서 inplace=False 옵션을 사용하면 연산결과가 "Output"에 나타납니다.
    df = pd.DataFrame({'A': [1, 2, 3]})
    new_df = df.drop('A', axis=1)

inplace 옵션의 사용은 데이터의 보존 및 메모리 관리 측면에서 중요합니다. 때로는 원본 데이터의 수정이 필요할 수 있지만, 다른 경우에는 원본 데이터를 유지하고 변형된 새로운 객체를 얻고 싶을 수 있습니다.

4. 가비지 컬렉터 (Garbage Collector)

파이썬에는 가비지 컬렉터라는 기능이 내장되어 있습니다. 프로그램 실행 중 더 이상 참조되지 않는 객체는 가비지 컬렉션의 대상이 될 수 있으며, 이런 객체들은 메모리에서 자동으로 해제됩니다. 가비지 컬렉터는 자동으로 작동하지만, 필요에 따라 수동으로도 제어할 수 있습니다.

비파괴적 연산과 가비지 컬렉션

비파괴적 연산을 수행하면 원본 데이터는 그대로 유지되며, 새로운 데이터나 객체가 생성됩니다. 이때, 원본 데이터에 대한 참조를 잃어버리게 되면 그 데이터는 더 이상 프로그램에서 접근할 수 없게 됩니다. 예를 들면:

data = [1, 2, 3]
data = sorted(data)  # 비파괴적 연산

위 코드에서 sorted(data)를 실행하면 정렬된 새로운 리스트가 반환되지만, data 변수에 다시 할당함으로써 원본 리스트에 대한 참조를 잃어버립니다. 이렇게 되면 원본 리스트는 가비지 컬렉터의 대상이 됩니다.

가비지 컬렉션의 중요성

비파괴적 연산 후 동일한 리퍼런스 변수를 재사용하면, 원본 데이터에 대한 참조가 사라져 메모리 상에서 불필요한 공간을 차지하게 됩니다. 이러한 "가비지"들이 쌓이게 되면 프로그램의 메모리 사용량이 불필요하게 증가하게 됩니다. 가비지 컬렉터는 이런 가비지들을 메모리에서 해제함으로써 불필요한 메모리 사용을 줄이는 중요한 역할을 합니다.

5. 가비지 컬렉터(Garbage Collector)와 머신러닝

머신러닝에서의 메모리 관리

머신러닝, 특히 딥러닝에서는 큰 데이터셋과 복잡한 모델을 사용하므로 메모리 문제에 주의해야 합니다. "MemoryError"는 할당하려는 메모리가 시스템에서 사용 가능한 메모리를 초과했을 때 발생합니다.

메모리 관리 전략

  1. 데이터 분할: 큰 데이터셋을 작은 배치로 나누어 처리합니다.
  2. 모델 단순화: 너무 복잡한 모델 대신 간단한 모델을 사용합니다.
  3. 메모리 최적화: 불필요한 변수 삭제, 데이터 타입 변경 등으로 메모리 사용량을 줄입니다.
  4. 가비지 컬렉션 강제 실행: gc 모듈을 사용해 중간중간 가비지 컬렉션을 수행하여 메모리를 해제합니다.
  5. 하드웨어 업그레이드: 더 많은 RAM 또는 GPU 메모리를 가진 시스템을 사용합니다.

하드웨어 업그레이드는 즉각적인 메모리 문제 해결에 좋은 방법이 될 수 있지만, 예산이 발생하기에 현실적으로 채택하기 어려운 방법일 수 있습니다. 근본적으로 문제를 해결하기 위해선 더 나은 알고리즘을 고안하고 데이터셋을 작은 배치로 나누어 처리하는 것이 되겠지만, 가비지 컬렉션을 사용하는 것도 메모리를 관리하기 위한 방법이 될 수 있습니다.

profile
돌고돌아

0개의 댓글