[python] 메모리 stack, heap, 소유권?

About_work·2024년 7월 8일
0

python 기초

목록 보기
60/65
def _generate_grid_map(self, local_lidar_xy_grid: np.ndarray) -> np.ndarray:
        """ grid cell을, unknown(-1), empty(0), occupied(1)로 업데이트합니다."""
        grid_map = np.full((self.grid_size, self.grid_size),
                                UNKNOWN,
                                dtype=int)  # -1 is unknown
        # Update empty cells (bresenham line) for each valid point
        for x, y in local_lidar_xy_grid:
            self.update_empty_cells(x, y, grid_map)

        # Update grid map with occupied points
        grid_map[local_lidar_xy_grid[:, 0], local_lidar_xy_grid[:, 1]] = OCCUPIED
        return grid_map
        
        
    def update_empty_cells(self, a_global_pcl_x_grid: int,
                           a_global_pcl_y_grid: int, grid_map: np.ndarray
                           ) -> None:
        grid_origin_x = grid_origin_y = self.grid_center
        line_points = self.bresenham_line(grid_origin_x, grid_origin_y,
                                          a_global_pcl_x_grid,
                                          a_global_pcl_y_grid)
        line_points = np.array(
            line_points[:-1])  # Exclude the last point (occupied)
        # Filter points that are within the grid bounds
        valid_points = (line_points[:, 0] >= 0) & (
                    line_points[:, 0] < self.grid_size) & \
                       (line_points[:, 1] >= 0) & (
                                   line_points[:, 1] < self.grid_size)

        # Apply the filter
        valid_line_points = line_points[valid_points]

        # Update the grid using advanced indexing
        grid_map[valid_line_points[:, 0],
                      valid_line_points[:, 1]] = FREE  # Set to empty

  • 위 파이썬 코드에서 메모리와 관련된 개념을 설명하겠습니다. 특히 grid_map의 메모리 관리와 함수 호출 간의 메모리 사용에 초점을 맞춰 설명하겠습니다.

힙(Heap)과 스택(Stack)

= 파이썬에서 변수와 객체는 각각 다른 메모리 영역에 저장됩니다.

  1. 스택(Stack):

    • 함수 호출 시, 함수의 지역 변수함수의 실행 상태(예: 반환 주소 등)가 스택에 저장
    • 예를 들어, update_empty_cells 함수의 파라미터 a_global_pcl_x_grid, a_global_pcl_y_grid, grid_map는 함수 호출 시 스택에 저장
    • 스택에 저장된 변수들은 함수 실행이 끝나면 자동으로 해제
  2. 힙(Heap):

    • 파이썬의 대부분의 객체(예: 리스트, 딕셔너리, numpy 배열 등)는 힙에 저장
    • grid_map과 같은 numpy 배열은 힙에 저장
    • 이 배열의 참조는 스택에 저장
    • 힙에 저장된 객체는 참조 카운트를 통해 관리되며, 더 이상 참조되지 않을 때 가비지 컬렉션을 통해 해제

소유권과 참조

  • 파이썬에서는 명시적인 소유권 개념이 없으며, 대신 참조(reference)와 참조 카운트를 사용합니다.

  • 참조:

    • grid_map은 numpy 배열 객체이며, 이 객체는 힙에 저장
    • grid_map 변수를 다른 함수에 인자로 넘기면, 그 함수에서도 동일한 객체를 참조하게 됩니다.
    • grid_mapupdate_empty_cells 함수의 인자로 넘길 때, 새로운 복사본이 생성되지 않고 동일한 객체에 대한 참조가 전달

코드 설명

def _generate_grid_map(self, local_lidar_xy_grid: np.ndarray) -> np.ndarray:
    """ grid cell을, unknown(-1), empty(0), occupied(1)로 업데이트합니다."""
    grid_map = np.full((self.grid_size, self.grid_size), UNKNOWN, dtype=int)  # -1 is unknown
    # grid_map은 힙에 저장되고, 이 객체에 대한 참조는 스택에 저장됩니다.

    # Update empty cells (bresenham line) for each valid point
    for x, y in local_lidar_xy_grid:
        self.update_empty_cells(x, y, grid_map)
        # 각 호출에서 grid_map은 동일한 힙 객체를 참조합니다.

    # Update grid map with occupied points
    grid_map[local_lidar_xy_grid[:, 0], local_lidar_xy_grid[:, 1]] = OCCUPIED
    return grid_map
  • 위 코드에서 grid_map은 numpy 배열로 힙에 저장되며, 함수 호출 시 스택에 있는 변수 grid_map이 이 객체를 참조
  • update_empty_cells 함수로 grid_map을 전달할 때도 동일한 힙 객체를 참조하게 됩니다.
  • 따라서 update_empty_cells 함수 내에서 grid_map을 수정하면, 그 수정 내용은 _generate_grid_map 함수에서도 반영
def update_empty_cells(self, a_global_pcl_x_grid: int, a_global_pcl_y_grid: int, grid_map: np.ndarray) -> None:
    grid_origin_x = grid_origin_y = self.grid_center
    line_points = self.bresenham_line(grid_origin_x, grid_origin_y, a_global_pcl_x_grid, a_global_pcl_y_grid)
    line_points = np.array(line_points[:-1])  # Exclude the last point (occupied)
    
    # Filter points that are within the grid bounds
    valid_points = (line_points[:, 0] >= 0) & (line_points[:, 0] < self.grid_size) & \
                   (line_points[:, 1] >= 0) & (line_points[:, 1] < self.grid_size)

    # Apply the filter
    valid_line_points = line_points[valid_points]

    # Update the grid using advanced indexing
    grid_map[valid_line_points[:, 0], valid_line_points[:, 1]] = FREE  # Set to empty
  • 위 코드에서 grid_map은 동일한 힙 객체를 참조하고 있으므로, update_empty_cells 함수 내에서 grid_map을 수정하면 해당 수정이 원본 grid_map에 반영됩니다.
profile
새로운 것이 들어오면 이미 있는 것과 충돌을 시도하라.

0개의 댓글