Virtualizable¶
참고: 이 문서에는 기본 개념을 이해하는 방법에 대한 제대로 된 소개가 없습니다. 소개 글을 작성해야 합니다. 혹시 이 문서를 보시다가 맥락을 파악하기 어렵다면, 언제든지 IRC에서 저희에게 편하게 물어보십시오.
문제 설명¶
JIT는 트레이스 밖으로 탈출하지 않는 객체가 아예 할당되지 않도록 만드는 데 매우 뛰어납니다. 이러한 객체를 virtuals라고 부릅니다. 그러나 프레임을 다룰 때는 virtual만으로 충분하지 않은 경우가 많습니다. 프레임은 탈출할 수 있으며, JIT에 진입하는 시점에 이미 할당되어 있을 수도 있습니다. 이런 경우에는 힙에 존재하더라도 여전히 최적화로 제거할 수 있는 추가적인 객체가 필요합니다.
해결책¶
가상화 가능 객체(virtualizable)를 도입합니다. 가상화 가능 객체는 힙에 존재하는 객체이지만, 그 필드가 어셈블러에서 일어나는 일과 항상 동기화되어 있지는 않습니다. 한 가지 예로, 가상화 가능 객체의 필드에는 가상 객체를 강제(force)하지 않고도 저장할 수 있습니다. 이는 프레임에 매우 유용합니다. 객체를 가상화 가능 객체로 선언하는 방법은 다음과 같습니다:
class Frame(object):
_virtualizable_ = ['locals[*]', 'stackdepth']
그리고 JitDriver에서는 이들을 다음과 같이 사용합니다:
jitdriver = JitDriver(greens=[], reds=['frame'], virtualizables=['frame'])
이 선언은 stackdepth가 virtualizable 필드이고, locals는 virtualizable 배열(virtualizable에 저장된 리스트)이라는 뜻입니다. virtualizable 사용에는 여러 규칙이 있으며, 특히 virtualizable 배열 사용에 관한 규칙은 매우 헷갈릴 수 있습니다. 이런 규칙을 어기면 대개 (이상한 동작 대신) 컴파일 타임 오류가 발생합니다. 규칙은 다음과 같습니다:
virtualizable 배열은 고정 크기 리스트여야 합니다. 배열이 초기화된 뒤에는(예:
Frame.__init__에서) 크기를 전혀 바꿀 수 없습니다. 해당 필드에 다른 리스트를 할당할 수 없으며, 리스트를 다른 곳으로 전달할 수도 없습니다.frame.array[index]처럼 직접 접근하는 것만 가능합니다.각 배열 접근에는
IndexError를 발생시킬 수 없는, 이미 알려진 양의 인덱스를 사용해야 합니다. 상수 인덱스로 접근하려면index = jit.hint(index, promote=True)를 사용하는 것이 유용할 수 있습니다. 이 방법은 사용자 코드의 맥락에서 인덱스가 실제로 상수이거나 거의 바뀌지 않을 때에만 안전합니다.JIT에서 새 virtualizable을 초기화하려면 다음과 같이 해야 합니다(예를 들어
Frame.__init__안에 있는 경우):self = hint(self, access_directly=True, fresh_virtualizable=True)
그렇게 하면 필드를 직접 채울 수 있습니다.
JIT 바깥에서 virtualizable을 사용하면 비용이 매우 크며, 때로는 트레이싱이 중단되기도 합니다. 매번 사용하는 대신 디버깅 목적으로만 사용하려면 어떻게 해야 할지 신중하게 고려하십시오(예:
sys._getframe호출).Python 제너레이터에 해당하는 것이 있어서 virtualizable이 더 오래 살아남는 경우에는 반환하기 전에 이를 강제(force)해야 합니다. 나중에 외부 호출로 처리하는 것보다 그렇게 하는 편이 더 낫습니다. 이는
jit.hint(frame, force_virtualizable=True)를 사용하여 수행합니다.인터프리터에는 위의
frame과 비슷한 지역 변수가 있어야 합니다. 이 변수는 인터프리터가jit_merge_point루프를 실행하는 동안에는 수정되어서는 안 되며, 루프 안에서는jit_merge_point()호출과can_enter_jit()호출에 직접 전달되어야 합니다. 수정되지 않은 같은 지역 변수를 재사용하지 않고 매 반복마다 virtualizable을 어딘가에서 가져오면 JIT 생성기가 버그가 있는 코드를 만들어 내는 것으로 알려져 있습니다.