[Ray] ActorHandle의 __hash__ 캐싱 및 __eq__ 정확성 수정
PR 링크: ray-project/ray#61638 상태: Merged | 변경: +63 / -15
들어가며
Ray의 ActorHandle.__hash__는 호출될 때마다 Python -> Cython -> C++ 전체 경로를 순회하고 있었다. Actor ID는 불변이므로 해시값을 캐싱할 수 있는데 그렇게 하지 않고 있었다. 또한 __eq__는 hash(self) == hash(other)로 구현되어 있어, 해시 충돌 시 서로 다른 actor를 동일하다고 판단하는 정확성 버그가 있었다.
핵심 코드 분석
Before: 매번 해시 재계산 + 부정확한 동등성 비교
def __hash__(self):
return hash(self._actor_id)
def __eq__(self, __value):
return hash(self) == hash(__value)
After: 해시 캐싱 + Actor ID 직접 비교
def __hash__(self):
# __dict__에서 직접 조회하여 __getattr__을 우회
# (cross-language actor에서 __getattr__이 ActorMethod를 반환하는 문제 방지)
try:
return self.__dict__["_ray_cached_hash"]
except KeyError:
h = hash(self._ray_actor_id)
self._ray_cached_hash = h
return h
def __eq__(self, other):
if not isinstance(other, ActorHandle):
return NotImplemented
return self._ray_actor_id == other._ray_actor_id
마이크로벤치마크 결과 (50 actors)
| 연산 | Before | After | 개선 |
|---|---|---|---|
| eq same (h == h) | 335 ns | 217 ns | -35% |
| eq different (a==b) | 331 ns | 209 ns | -37% |
| eq non-ActorHandle | 206 ns | 78 ns | -62% |
| dict insert d[h]=i | 151 ns | 106 ns | -30% |
| dict lookup d[h] | 128 ns | 86 ns | -33% |
왜 이게 좋은가
- 해시 캐싱: 불변 ID의 해시를 한 번만 계산하고 캐싱하여, dict/set 연산에서 반복 해시 계산을 제거한다.
- 정확성 수정:
hash(a) == hash(b)는 해시 충돌 시 false positive를 만든다. Actor ID 직접 비교로 정확한 동등성을 보장한다. - NotImplemented 반환: 비 ActorHandle 타입과의 비교에서
NotImplemented를 반환하여 Python의 비교 프로토콜을 올바르게 따른다. - Ray Data 핵심 경로: Ray Data의 actor pool operator는 ActorHandle을 dict 키로 빈번하게 사용하므로, 이 최적화의 실제 영향이 크다.
참고 자료
관련 포스트
PR Analysis 의 다른글
- 이전글 [Ultralytics] SAM-2 문서에 YOLO26 벤치마크 및 참조 추가
- 현재글 : [Ray] ActorHandle의 __hash__ 캐싱 및 __eq__ 정확성 수정
- 다음글 [Ray] Parquet 배치 크기를 C++ 32비트 정수 범위로 클램핑하여 OverflowError 수정
댓글