멀티쓰레딩 프로그래밍에서 락을 잡는 타이밍이 짧다면 이론적으로 spin lock을 사용하여 busy waiting을 하는 것이 성능에 좋다고 알고 있다.

하지만, 실제로 spin lock으로 효과를 보기 쉽지 않은데, CPU에 이를 위해 pause라는 명령어가 존재한다.

spin lock이라는게 결국 변수의 값이 원하는 값이 될때까지 계속 loop를 돌리는 것인데, pause라는 명령어를 통해 CPU에게 지금 spin loop를 돌고 있다는 힌트를 주고, CPU가 메모리버스 속도 등을 감안해서 변수가 바뀌는데 필요한 최소한의 시간만큼 다음 명령어를 실행하지 않는 것이다.

– 참고 https://software.intel.com/sites/default/files/m/d/4/1/d/8/17689_w_spinlock.pdf (w_spinlock.pdf)

이를 테스트 해보았다.

인텔계열의 CPU에서는 _mm_pause();라는 함수로 pause를 사용 할 수 있다.

  • Visual Studio에서는 YieldProcessor(); 라는 매크로 함수도 동일하다.

간단하게 코드를 보면

실제로 pause 명령어를 사용했을 때와 안했을 때를 테스트 해봤을 때….

어마어마한 차이가 났다.

 

테스트 케이스는 I7-6700K CPU (8코어) 에서 8개의 쓰레드에서 스핀락을 걸고, 스핀락이 성공하면 Sleep(0)로 잠깐 휴지기를 주었으며, 시간 측정은 spin-loop 구간만 측정하였다.

결과는…

실행할때마다 결과가 다르긴 한데… 10배이상의 차이가….