MSDN에 있는 글을 옮겨와 봤습니다^^

 

다른 프로세서에서 사용되고 있는 복수의 동시실행 태스크가 같은 캐시라인에 배치되어 있는 변수에 쓰기를 하면 거짓 공유가 발생한다. 하나의 태스크가 어떤 변수에 쓰기를 하면 양쪽 변수의 캐시라인이 무효화된다. 캐시라인이 무효화 될 때마다 재 로딩이 필요하게 된다. 즉 거짓 공유가 발생하면 애플리케이션의 성능이 저하할 위험이 크다.

 

long count1 = 0L;

long count2 = 0L;

concurrency::parallel_invoke(

   [&count1] {

      for(int i = 0; i < 100000000; ++i)

         ++count1;

   },

   [&count2] {

      for(int i = 0; i < 100000000; ++i)

         ++count2;

   }

);

long count = count1 + count2;

위의 코드는 태스크에 공유 변수를 사용하지 않기 위해 count1, count2로 변수를 나누어서 사용하고 있다. 그래서 일견 보기에는 서로 독립적으로 실행될 것이라고 생각할 수 있다. 그러나 위에 설명했듯이 count1 count2는 서로 같은 캐시라인에 배치될 확률이 높아서 결과적으로 거짓 공유가 발생한다.

 

이 문제를 해결하기 위해서는 아래처럼 메모리 정렬에 의해 서로 다른 캐시라인에 배치되도록 한다.

__declspec(align(64)) long count1 = 0L;     

__declspec(align(64)) long count2 = 0L;     

concurrency::parallel_invoke(

   [&count1] {

      for(int i = 0; i < 100000000; ++i)

         ++count1;

   },

   [&count2] {

      for(int i = 0; i < 100000000; ++i)

         ++count2;

   }

);

long count = count1 + count2;

핵심은 __declspec(align(64))으로 메모리 캐시 사이즈가 64바이트 이하인 경우 같은 캐시라인을 사용하지 않도록 해준다.

 

 

__declspec 설명

http://blog.naver.com/riverrun27/40126498899

 

 

by 흥배 2014. 2. 3. 08:00
  • 크로스 2014.02.03 10:30 ADDR EDIT/DEL REPLY

    msdn에 있는 내용이면 VS계열의 컴파일러에서만 동작하는 키워드인가요?
    gcc등으로 컴파일해서 리눅스계열의 운영체제에서 돌아갈 수 있는 프로그램은 못만드나 싶어서 여쭤봅니다 ^^;;
    만약 어떤 프로그램을 리눅스로 개발해야 한다면 위 키워드는 사용할수 없는지요?

    • 흥배 2014.02.03 15:43 신고 EDIT/DEL

      구글링 해보니 gcc에서는 __attribute__ 라는 키워드를 사용한 것 같습니다. http://stackoverflow.com/questions/7281699/aligning-to-cache-line-and-knowing-the-cache-line-size

  • ruwin126 2014.05.01 22:15 ADDR EDIT/DEL REPLY

    캐시 라인이 64 byte 이하여야 하고(이건 지금 나오는 대부분의 머신이 만족하겠지만) 120바이트의 낭비되는 공간이 있다는 것에서 딱히 추천할 만한 방법은 아닌 것 같네요.
    combinable을 이용하는건 어떻게 생각하세요?

| 1 |