상각 된 일정한 시간에 배열을 초기화합니다.이 트릭은 무엇입니까?


13

이 데이터 구조는 배열 액세스 성능을 지우는 동안 반복해야 할 필요성에 대비하여 거래합니다. 각 항목마다 생성 카운터와 글로벌 생성 카운터를 유지합니다. "클리어"조작은 생성 카운터를 증가시킵니다. 각 액세스에서 로컬 및 글로벌 세대 카운터를 비교합니다. 서로 다른 경우 값은 "깨끗한"것으로 처리됩니다.

이것은 최근 Stack Overflow 의이 답변에서 나왔지만이 트릭의 공식 이름이 있는지 기억이 나지 않습니다. 그렇습니까?

하나의 사용 사례는 노드의 작은 하위 집합 만 완화하고 반복적으로 수행 해야하는 경우 Dijkstra의 알고리즘 입니다.


2
재미있는 트릭이지만 오버 헤드가 상당히 많습니다. 그렇다면 가격이 지불하는 일반적인 작업으로 배열을 지우는 용도가 무엇인지 궁금합니다. (Sincere question!)
Joachim Sauer

@JoachimSauer : 편집했습니다.
krlmlr

일반적으로 메모리 사용량과 액세스 비용 모두에 대해 매우 비싸게 들립니다. 이 기술의 사용 사례는 매우 구체적이어야합니다.
마틴 요크

3
@Joachim : 렌더링을 위해 버퍼를 빠르게 지우는 데 사용됩니다. 그들은 64kb 당 또는 그와 비슷한 "클리어 비트"를 가지고 있습니다.
DeadMG

3
@ user946850 "amortized"는 전체 그림에서 값 비싼 작업이 거의 발생하지 않음을 증명할 수 있음을 의미합니다. 예를 들어 O (1)

답변:


2

전술 한 접근법은 각각의 셀이 어레이가 재 초기화 될 필요가있는 횟수를 보유하기에 충분한 수를 보유 할 수 있어야하며, 이는 실질적인 공간 페널티이다. 슬롯 정당하게 기록되지 않을 적어도 하나 개의 값을 보유 할 경우, 하나는 추가의 비용 다른 (일정하지 않은) 공간 페널티 것을 방지 할 수있다 O(Wlg(N))시간 페널티 여기서 W의 개수를 구별 사이 기입 어레이 슬롯 지우기 작업이며 N배열의 크기입니다. 예를 들어, -2,147,483,647에서 2,147,483,647 (그러나 절대 -2,147,483,648은 아님)의 정수를 저장하고 빈 배열 항목을 0으로 읽길 원한다고 가정하십시오. 배열을 -2,147,483,648로 채움으로써 시작하십시오 (그 값을 호출하십시오)B). 애플리케이션의 어레이 슬롯을 읽을 때 값을 B0으로 보고하십시오 . 슬롯 배열을 작성하기 전에 I, 그 유지 여부를 확인 B하고 만약 그렇다면 I1보다 크면, 슬롯 0을 저장하는 것이다 I/4(이 경우, 유지하고, 그 위치에 대해 유사한 체크를 수행 한 후 B, I/16등).

배열을 지우려면 I배열 기준에 따라 0 또는 1로 시작 하십시오 (설명 된 알고리즘이 작동합니다). 그런 다음 다음 절차를 반복하십시오. item I이 인 B경우 증가 I하고 4의 배수를 생성하면 4로 나눕니다 (분할이 1의 값을 생성하면 종료). item I이 아닌 경우 거기 B에 저장 하고 4를 B곱하십시오 I( I0에서 시작하면 4를 곱하면 0이되지만 항목 0이 비어 있기 때문에 I증가합니다).

위의 상수 "4"를 다른 숫자로 대체 할 수 있으며, 값이 클수록 일반적으로 작업 태깅이 덜 필요하지만 값이 작을수록 일반적으로 작업 지우기가 덜 필요합니다. 태그가 지정된 배열 슬롯을 지워야하므로 3-4의 값이 거의 최적입니다. 값 4는 확실히 최적에 가깝고 2 또는 8보다 낫고 다른 숫자보다 편리하기 때문에 가장 합리적인 선택이 될 것입니다.


모든 셀이 새로운 값으로 업데이트되기 전에 충분한 순차적 재설정을 수용 할 수있는 버전 카운터를 갖는 것으로 충분합니다. 실제로 바이트는 충분하거나 더 엄격한 루프에서는 적을 수 있습니다.
9000

@ 9000 : 그러한 행동에 의존하는 코드는 취약하기 쉽다. 특히 그러한 '의사 제거'접근법을 사용하는 유일한 이유는 (단순히 배열을 지우는 것이 아니라) 필요한 항목 세트가 제거되는 것은 일반적으로 작고 가변적이었다. 한 쌍의 조건은 아이템이 사용될 가능성을 높이고 "지워진"후 임의로 오랫동안 손대지 않은 상태로 유지된다. 카운터가 줄 바꿈 될 때 어레이를 스캔하고 오래된 슬롯을 물리적으로 지우는 것을 고려할 수 있지만 ...
supercat

1
... 카운터의 줄 바꿈 값이 일정하면 각 배열 지우기 작업의 평균 작업량은 O (N)이며 N은 배열 크기입니다. 실제로 65,536 배로 증가 된 O (N) 구현은 여전히 ​​O (N) 일뿐 아니라 비 개선 된 것보다 65,536 배 빠르기 때문에 그러한 것은 실제로 유용하지 않을 수 있습니다. . 또한, 이러한 접근 방식이 도움이되는 경우도 O (AlgN) 공간을 사용하여 공백이 아닌 요소가있는 N 크기의 배열을 보유 할 수있는 희소 배열 데이터 구조를 사용하면 도움이 될 수 있습니다.
supercat

1

"게으른 배열 셀 재 초기화"라고 부르지 만 이름이 정해져 있지 않은 것 같습니다 (즉, 이름이 널리 사용되고 있음).

이 알고리즘은 영리하지만 매우 전문적이고 매우 좁은 영역에 적용 할 수 있습니다.


1

이 경우를 제외하고는 "memos"가 전역 카운터의 각 증분에 따라 암시 적으로 "age"인 경우를 제외하고 는 특별한 메모의 경우라고 생각합니다 . 나는 일종의 "뒤로 메모"를 추측합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.