다음과 같은 매우 간단한 컴퓨터 프로그램을 고려하십시오.
for i = 1 to n:
y[i] = x[p[i]]
여기서 와 y 는 바이트의 n 요소 배열이고, p 는 단어 의 n 요소 배열입니다. 여기서, n 은 예를 들어 n = 2 31 이므로, 데이터의 무시할만한 부분 만이 임의의 종류의 캐시 메모리에 적합하다.
가 1 과 n 사이에 균일하게 분포 된 난수 로 구성되어 있다고 가정합니다 .
최신 하드웨어의 관점에서 이것은 다음을 의미해야합니다.
- 읽는 것이 저렴합니다 (순차적 읽기)
- 읽기 는 매우 비쌉니다 (무작위 읽기; 거의 모든 읽기는 캐시 미스입니다. 주 메모리에서 각 개별 바이트를 가져와야합니다)
- 쓰기 는 저렴합니다 (순차 쓰기).
그리고 이것은 실제로 내가 관찰하고있는 것입니다. 프로그램은 순차적 읽기 및 쓰기 만 수행하는 프로그램과 비교할 때 매우 느립니다. 큰.
이제 질문이 온다 : 이 프로그램 은 현대 멀티 코어 플랫폼에서 얼마나 잘 병렬화 되는가?
내 가설은이 프로그램이 잘 평행하지 않다는 것이었다. 결국 병목 현상이 주요 메모리입니다. 단일 코어는 이미 주 메모리에서 일부 데이터를 기다리는 데 대부분의 시간을 낭비하고 있습니다.
그러나 병목 현상이 이런 종류의 작업 인 알고리즘을 실험하기 시작했을 때 이것은 내가 관찰 한 것이 아닙니다 !
필자는 순진한 for-loop를 OpenMP 병렬 for-loop로 간단히 교체했습니다. 본질적으로 범위 를 더 작은 부품으로 나누고이 부품들을 다른 CPU 코어에서 병렬로 실행합니다.
저가형 컴퓨터에서는 실제로 속도가 약간 떨어졌습니다. 그러나 고급 플랫폼에서 나는 거의 선형에 가까운 속도 향상을 얻고 있다는 것에 놀랐습니다. 몇 가지 구체적인 예 (정확한 타이밍이 약간 떨어져있을 수 있으며 임의의 변형이 많으며 빠른 실험이었습니다) :
4 코어 Xeon (총 8 코어) 2 개 : 단일 스레드 버전과 비교하여 5-8 속도 향상.
2 개의 6 코어 Xeon (총 12 코어) : 단일 스레드 버전과 비교하여 8-14 속도 향상.
이제 이것은 완전히 예기치 않은 일이었습니다. 질문 :
정확히 이런 종류의 프로그램이 왜 그렇게 잘 평행 화 되는가? 하드웨어는 어떻게 되나요? (현재 나의 추측은 다음 줄을 따른 것입니다. 다른 스레드에서 임의의 읽기는 "파이프 라인"되어 있으며 이것에 대한 평균 응답 속도는 단일 스레드의 경우보다 훨씬 높습니다.
그것은이다 다중 스레드 및 멀티 코어를 사용할 필요가 있는 속도 향상을 얻을? 메인 메모리와 CPU 사이의 인터페이스에서 실제로 파이프 라이닝이 발생하면 단일 스레드 응용 프로그램에서 메인 메모리에 , x [ p [ i + 1 ] ] , ... 컴퓨터가 주 메모리에서 관련 캐시 라인을 가져 오기 시작할 수 있습니까? 이것이 원칙적으로 가능하다면 실제로 어떻게 달성합니까?
이런 종류의 프로그램을 분석 하고 성능 을 정확하게 예측하는 데 사용할 수 있는 올바른 이론적 모델 은 무엇입니까 ?
편집 : 이제 여기에 몇 가지 소스 코드와 벤치 마크 결과가 있습니다 : https://github.com/suomela/parallel-random-read
야구장 수치의 일부 예 ( ) :
- 약. 단일 스레드에서 반복 당 42ns (무작위 읽기)
- 약. 12 개의 코어가있는 반복 당 5ns (무작위 읽기)