정답: 다음 코드의 문제점은 false sharing

퀴즈: 다음 코드의 문제점은?

두 스레드에서 각기 다른 변수를 업데이트를 하는 코드였다. 코드에는 전혀 문제가 없으나 성능이라는 관점에서 보면 문제가 있는 코드였다. 문제점은 바로: false sharing. 멀티코어 시스템에서 일어날 수 있는 대표적인 성능하락 주범 중 하나이다. 나도 그냥 얼마나 이게 영향을 미치는가 보기 위해 테스트해봤는데 꽤 큰 수치가 나옴을 알 수 있었다. False sharing을 그림으로 대략 나타내면 아래와 같다.

image

위 그림은 엑셀로 1분만에 그린 대략적인 캐쉬의 모습. 4-way set-associativity 캐쉬를 그렸고, 주황색 한 블럭은 4바이트를 가리킨다. 그래서 캐쉬 라인의 크기는 64바이트이다. Core 2 Duo 같은 경우는 L2 캐쉬는 공유되어있고 L1 캐쉬가 각자 private 캐쉬니까 false sharing은 L1 레벨에서 일어날 것이다.

False sharing의 자세한 설명은 예전에 쓴 글을 참조하면 되고, 매우 간단히 설명하면: 빨간 색 두 블럭으로 표현된 두 4바이트 데이터가 두 스레드로부터 접근된다고 하자. 이 캐쉬는 한 코어의 모습이고, 듀얼 코어라면 이런 상태가 두 코어에게 존재한다. 그런데 이 두 빨간 데이터는 서로 공유되지 않고 있다. 그런데 같은 캐쉬 라인에 올라와있기 때문에 어느 한쪽이 여기에 데이터를 쓰면 다른 쪽 캐쉬에게 이 라인을 무효화 시키게 된다. 그래서 각 스레드가 데이터를 쓰려고 할 때 마다 캐쉬 라인을 무효화 시키기 때문에 성능 하락이 일어난다.

반면, 녹색 블럭으로 표현된 데이터는 다른 캐쉬 라인에 있기 때문에 어느 한 쓰레드가 이 데이터를 고쳐도 무효화 신호를 보낼 필요가 없기 때문에 빠르게 자기 사본만 업데이트를 할 수 있다.

당연히 private cache가 없는 싱글코어 CPU나 하이퍼스레딩 CPU는 이런 일이 벌어지지 않는다. 만약, L2 캐쉬도 각각 독립적인 예전 Pentium-D라면 성능 하락은 더욱 클 것 같다.

사실 원 문제에 있던 코드는 조금 억지이다. 그런데 이런 경우는 malloc을 이용할 경우에도 얼마든지 일어날 수 있다. 두 스레드가 malloc으로부터 각각 4바이트를 할당 받고 접근한다고 생각해보자.

DWORD CALLBACK TestThread1(void* arg)
{
volatile int& data1 = *((int*)malloc(4));
_tprintf(_T("%d\n"), &data1);
for (int i = 0; i < 500000000; ++i)
data1 = data1 + 1;
return data1;
}

DWORD CALLBACK TestThread2(void* arg)
{
volatile int& data1 = *((int*)malloc(4));
_tprintf(_T("%d\n"), &data1);
for (int i = 0; i < 500000000; ++i)
data1 = data1 + 1;
return data1;
}

만약, 위 코드에서 각 스레드가 할당 받은 데이터의 주소가 8421184, 8421200와 같이 16바이트 정도만 떨어져있다면, 위 그림의 빨간 블럭처럼 같은 캐쉬라인에 배치될 확률이 높다. 그렇게 되면 위의 설명한 일이 고스란히 벌어지고 성능 하락이 된다. 이런 false sharing이 일어날 경우, 위 코드는 약 1.5초가 걸렸으며, false sharing이 일어나지 않도록 좀 떨어져서 메모리가 할당되게 해보니 1.15초 정도가 나왔다. 물론 이런 코드는 극단적이지만 30%라는 결코 무시할 수 없는 성능 차이가 있다. 고성능 서버나 속도가 단 1초라도 중요한 코드에서는 이런 점을 고려해야할 것이다.

사실 이런 문제는 운에 달려있다. malloc이 어떤 방식으로 메모리를 줄지 예측하기는 불가능하다. 그래도 익히 알려진 malloc 알고리즘을 가지고 유추해볼 때, 보통은 근접한 메모리가 할당된다. 그래서 이런 경우 문제 해결이 쉽지 않다. 대안으론 각 스레드마다 별도의 힙 할당 관리자를 둘 수도 있다. 마찬가지로 원래 퀴즈에 있었던 코드도 그 데이터가 어떤 주소에 할당될지 예측하기가 쉽지 않다.

그래도 원래 코드의 문제점을 해결한 코드를 대략 써보면 아래와 같다. 단순히 data1, data2 선언 사이에 넉넉하게 배열을 선언한다고 해서 쉽게 해결되지는 않았다. 왜냐면 전역 공간에 할당된 변수들의 주소가 선언대로 할당되는 것이 아니었다. 직접 data1, data2 메모리 주소를 찍어보면 여전히 인접하게 할당되었다 (VC++ 컴파일러는 그랬음). 그래서 구조체로 감싸는 방법으로 회피하였다.

volatile struct {
int data1;
int data[32];
int data2;
} DATA;

DWORD CALLBACK TestThread1(void* /*arg*/)
{
_tprintf(_T("Thread1: %d\n"), &DATA.data1);
for (int i = 0; i < 500000000; ++i)
DATA.data1 = DATA.data1 + 1;
return DATA.data1;
}

DWORD CALLBACK TestThread2(void* /*arg*/)
{
_tprintf(_T("Thread2: %d\n"), &DATA.data2);
for (int i = 0; i < 500000000; ++i)
DATA.data2 = DATA.data2 + 1;
return DATA.data2;
}

이런식으로 할 경우 확실하게 두 데이터가 다른 캐쉬 라인에 올라가는 것을 보장할 수 있으므로 성능 저하를 막을 수 있다. 그리고 테스트를 좀 세밀히 해보니 정확하게 Core 2 Duo의 캐쉬 라인 사이즈인 64바이트만큼 간격이 확보될 때, 성능이 개선됨을 찾을 수 있었다. 아주 심심한 분들께선 한번 직접 테스트해보고 성능 차이를 올려주시면 고맙겠습니다. 해당 CPU도 같이 써주시면 고맙겠습니다.

 

// 코멘트들에 대한 답변:

kc님: 정확하게 말씀하셨습니다. 오래전에 쓴 글인데 아직까지 기억하시는군요 :)

까막님: 용어는 다소 틀렸지만 cache invalidation은 맞습니다. 그리고 보다시피 이건 힙에서도 얼마든지 일어날 수 있습니다.

uriel님: 이 경우에는 두 스레드 사이에 명시적인 데이터 공유가 없는 상황입니다. 그래서 락 혹은 atomic operation을 쓸 필요는 없습니다. 혹시 Interlocekd*를 써서 코드를 돌려보시면 알겠지만 코드가 엄청나게 느려집니다. 테스트해보니 1초 걸리는 코드가 20초가 되네요.. 락이나 atomic increment는 상당한 오버헤드를 유발합니다.

rein님: 인텔 TBB (Thread Building Block)에서 제공되는 malloc은 false sharing을 피하기 위해 malloc을 캐쉬 라인 단위로 뛰어가며 하는 것 같네요. 멀티코어에서 사용되는 malloc은 당연히 이런 점을 고려해야 합니다.

자연푼선생: 이 경우는 스레드 각각이 각기 다른 물리코어에 할당되어 돌아갑니다. 물론 이건 운영체제 스레드 스케쥴링 정책에 따라 다르지만 거의 이런 경우 독립적인 코어에 스레드가 할당이 되기 때문에 이 둘 사이의 컨텍스트 스위칭으로 인한 비용은 없습니다. 만약 싱글 코어에서 이렇게 만들면 컨텍스트 스위칭 비용이 상당합니다. 테스트해보니 당연히 두배로 증가합니다 :) 테스트를 하기 위해서는 아래 함수를 불러주세요.

SetProcessAffinityMask(GetCurrentProcess(), 1);

즉, CPU 1번에만 이 프로세스의 스레드들이 올라가게 합니다. 3을 주면 CPU 1, 2번에게 할당 됩니다. 그래서 여담이지만 CPU 개수만큼 빡세게 돌아가는 스레드를 만드는 것이 좋습니다.

이홍석님: 위에 답변도 있었지만 x++과 x = x + 1은 x86으로서는 완전히 동일한 코드가 나옵니다.

orge님: 싱글코어에서는 캐쉬 사본이 존재하지 않으므로 서로의 사본을 무효화시키라는 메세지도 발생할 일이 없습니다. Core 2 Duo는 오히려 Shared L2 캐쉬이므로 이런 경우 이득을 볼 수 있을 것 같습니다. Pentium D 같은 private L2 캐쉬 구조에서는 더 성능이 하락될 것 같습니다. 요건 추측이고 직접 테스트를 해봐야겠네요. 참고로 Core 2 Duo에서는 약 20% 정도의 성능 차이가 있었습니다.

by object | 2008/04/17 14:23 | 컴퓨터 | 트랙백(1) | 핑백(2) | 덧글(28)
트랙백 주소 : http://minjang.egloos.com/tb/1848130
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from Trust Of Lyn.. at 2008/04/17 18:16

제목 : 듀얼 코어 이상에서 서로 다른 캐시라인에 메모리 올리기
VIsual C++ 에서는 __declspec(align(#))GCC 에서는 __attribute__ ((aligned (#)))키워드를 쓰면 메모리 할당을 조절 할 수 있다.듀얼 코어 이상에서 접근 할 경우는 캐시라인크기(64byte) 이상 떨어져 있어야 제대로 된 성능이 나온다.서로 다른 쓰래드에서 같은 캐시라인에 있는 블록을 접근하는 순간 캐시가 무효화되며 (동기화 해야 하기 때문에) 속도가 느려진다.듀얼코어가 아닌 CPU(하이퍼 쓰래딩 ......more

Linked at art.oriented : 병.. at 2009/11/16 07:24

... 돌아가게 하는 것도 굉장히 어려운데, 이걸 효과적으로 돌아가게 하는 것도 비슷한 수준으로 어렵다. 위에서 간단하게 보여준 privatization의 문제점은 사실 명백하다. False sharing이라는 아주 유명한 문제인데, 어떤 데이터가 스레드 사이에서 실제로는 공유가 되지 않음에도 불구, 하드웨어 캐시 구조의 특성으로 공유되는 것과 같은 효과를 내어, 성능 ... more

Linked at The truth will s.. at 2009/11/17 18:56

... 분 38초 넘게 사용되었다. 어째서 수행 시간이 더 늘어난 것일까? 더군다나 pi값도 틀리게 출력된다. 수행시간의 오버헤드는 True-sharing, False-sharing 때문에 발생한다. True-sharing은 복수개의 CPU가 공유 변수인 x, sum을 접근하려고 할 때 발생시키는 cache miss 오버헤 ... more

Commented by uriel at 2008/04/17 14:47
제가 착각했네요. Interlocked 연산이 SMP에서 쓰일 경우 memory barrier를 추가한다고 되어 있었는데, 제가 barrier() 연산을 잘못 이해했습니다.
Commented by 방준영 at 2008/04/17 15:39
안녕하세요. 구조체로 감싸는 것보다는 해당 컴파일러가 제공하는 기능을 쓰면 더 깔끔하게 됩니다. VC++에선 __declspec(align(#))을 쓰면 되고, GCC에선 __attribute__ ((aligned (#)))을 쓰면 됩니다. 그리고 Pentium D에서 실행해보니 예측하신 것처럼 200% 이상의 엄청난 성능 하락이 있었습니다. Core 2 Duo에선 object님과 비슷하게 20% 정도였구요.
Commented by object at 2008/04/17 15:49
우와 정말로 감사합니다. 200%면 진짜 장난아니에요... 후덜덜... __declspec이 있었군요. 감사합니다..

#define CACHE_LINE 32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))

struct CACHE_ALIGN S1 // cache align all instances of S1{
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned
Commented by 까막 at 2008/04/17 17:22
win32 CRT의 malloc은 page단위로 allocation하는 것으로 알고 있습니다. x86상에서는 아마 4K단위였던걸로 기억되네요. malloc(4)를 계속 반복해보면 4K씩 메모리가 증가했던걸로.. ( '')

제가 기억하는게 맞다면 false sharing문제는 해결이 되겠지만 메모리 공간낭비가 덜덜....

ps. boost::pool이나 직접 만든 메모리 관리자를 즐겨 쓰는데.. 성능면에서 문제가 발생할 소지가 농후한거였군요. (생각해보니 64byte내의 근접메모리주소를 여러쓰레드가 동시에 접근할 일은 별로 없어서 다행입니다. 휴우.

방준영// 오랜만입니다. :) 여기서 뵙네요.
Commented by object at 2008/04/17 17:33
흠.. Win32 힙 관리자는 그렇게 메모리를 할당하지 않습니다 (정확하게는 Win32 CRT는 아니고 Win32 API가 제공하는 Heap* 함수로 Win32 CRT의 malloc이 구현되어있습니다). 4KB 단위로 메모리를 할당하면 난리도 아니죠. malloc은 조금이라도 메모리를 아끼기 위해 수 많은 테크닉이 동원된 함수입니다. malloc의 본질은 운영체제가 제공하는 메모리 함수를 이용하여 페이지 단위의 큰 메모리를 얻어와서 작은 크기로 짤라 주는 함수죠. 512바이트 이하의 메모리에 대해서 매우 최적화 되어있습니다.

항상 그런 것은 아니지만, malloc(4)를 연속적으로 해보면 인접한 주소가 나옵니다. 그래서 얼마든지 false sharing 문제를 만들어낼 수 있습니다. 위의 경우에도 다른 스레드에서 호출된 두 번의 malloc의 결과가 각각 8421184, 8421200 였습니다. 고작 16바이트 차이입니다. 그래서 false sharing이 일어나지요... 현재 malloc은 false sharing을 전혀 해결할 수 없습니다. malloc은 Win32의 구현이 있고 glibc에 쓰이는 dmalloc이 있고 Sun에 쓰이는 알고리즘이 있는데 거의 대동소이합니다.
Commented by 까막 at 2008/04/17 17:41
음 저도 기억이 의심스러워서 다시 해보니 근접한 메모리주소가 나오네요.
전에 테스트했던 결과는 뭐였는지 가물가물해집니다. -_- 분명히 4K씩 증가하는 뭔가가 있었던거 같은데 말이죠.
(왠지 귀신에 홀린 기분입니다. 아 쪽팔려라)

덤으로 malloc의 결과주소를 검사해보니 VC2005는 0x10씩 증가하고, VC2003은 0x30씩 증가하네요. (뭐 정확한 값은 아닐지도 모르겠지만요.)

(아 정말 제가 기억하고 있던건 대체 어떤 실험이었을까요. -_-)
Commented by object at 2008/04/17 17:44
쪽팔린거 아닙니다 ㅎㅎ 요청한 메모리가 크면 페이지 단위로 나올 수 있습니다. 그리고 malloc의 행동이 컴파일러에 의존적이지는 않을 것 같은데... 잘 모르겠네요. 왜냐면 VC++ malloc은 그냥 결국 Win32 HeapAlloc으로 연결됩니다. Release 모드에서 컴파일 해보면 거의 redirect 수준입니다. 디버그 모드에서는 각종 canary value를 심어서 디버깅에 활용하죠.
Commented by 까막 at 2008/04/17 18:07
다시해보니 컴파일러 차이가 아니라 CRT의 차이였네요. 버젼차이가 아니라 멀티 스레딩용을 쓰느냐 싱글 쓰레딩용을 쓰느냐의 차이입니다. :) 2003의 단일쓰레딩에 당했습니다.. OTL

그러고보니 2005에는 코드생성탭에 단일쓰레드 항목이 아주 존재하지 않는군요.
Commented by object at 2008/04/17 18:09
네.. VS 2005는 아예 싱글스레드 라이브러리가 빠졌습니다 ㅎㅎ 그래서 많은 CRT 코드들에서 조건부 컴파일러가 빠졌죠.
Commented by kkamagui at 2008/04/20 13:30
Pentium D 1.8에 램 1G 정도에서 테스트 했을 때, 고치기 전 코드가 1430ms, 고친 후에 코드가 1380ms 정도 나왔습니다. ^^)/~ 확실히 효과가 있긴 있네요 ;)
제보해 드리고 갑니다. ^^)/~
Commented by object at 2008/04/20 13:39
엇.. 차이가 너무 없는 것 아닌가요? 1430ms랑 138ms는 거의 차이가 없는 것 같은데요. 윗분은 Pentium D 같은 Private L2 캐쉬가 있는 곳에서는 200% 이상 차이가 난다고 했는데 아마 고치기 전 코드도 다른 캐쉬라인에 올라간 것 같군요. 최악의 성능을 확인하려면 두 스레드가 아예 같은 데이터를 고치도록 해보세요. 즉, 두 스레드가 똑같이 data1을 고치도록 하는 코드가 최악의 경우입니다.
Commented by 방준영 at 2008/04/21 01:14
재미있는 점을 발견했는데, false sharing을 방지하면 Pentium D 820(2.80GHz)이 Core 2 Duo E6600(2.4GHz)보다 거의 클럭 주파수에 비례하게 빠릅니다. 일반적인 성능은 C2D가 압도적으로 빠르기 때문에 좀 의외의(?) 결과였습니다.

kkamagui//Pentium D 1.8이란 모델은 아마도 싱글코어 Pentium 4 1.8GHz 프로세서를 말씀하신 것 같습니다. 그렇다면 둘간의 차이가 별로 없어도 이상한 일이 아니지요. :-) 참고로 가장 느린 Pentium D가 2.66GHz입니다.

까막//오랫만입니다. :-)
Commented by object at 2008/04/21 02:49
클럭에 비례하게 빠른 건 충분히 그럴 수 있습니다. 저 코드가 보면 수행시간의 대부분이 루프에서 간단한 덧셈인데 덧셈은 1사이클이면 충분하고 저런 간단한 형태의 루프는 분기예측도 거의 확실하고 또 메모리 연산이 거의 없습니다. 아무리 volatile을 붙여도 그 캐쉬라인이 공유되지 않는 이상 캐쉬에만 업데이트만 되기 때문에 이건 C2D와 거의 속도 차이가 없습니다. 그래서 저런 코드는 거의 클럭에 비례하는 성능 차이가 나오겠네요.
Commented by 조성경 at 2008/05/09 15:52
시간이 많이 흘렀지만, 확인이 꼭 필요해서 답글 남깁니다. 보실지 모르겠네요.

일단 제 시스템은 XP + SP3, VS2005, C2D E8200 입니다. 이 환경에서 두 변수 사이의 거리에 관계 없이 결과는 항상 같습니다. 차이가 없다는 말이죠.

전에 글을 보면서 다들 그렇다고 해서 넘어 갔었는데 도저히 이해 할 수 없는 상황이네요. 컴파일 옵션등의 차이가 이러한 차이를 만든다고는 도저히 생각할 수가 없습니다. 혹 저와 비슷한 환경에서 성능 차이가 없으신분 있으신가요?
Commented by object at 2008/05/09 15:58
한번 두 스레드가 동일한 변수를 고치도록 해보세요. 그 경우가 최악의 경우이고, 데이터가 서로 달라도 같은 캐쉬 라인에 올라와있으면 같은 변수를 고칠때와 같은 수준의 성능이 나옵니다. E8200도 코어2듀오니까 비슷한 경향이 나와야 하는데 이상하네요. 캐쉬 라인 사이즈가 바뀌었을리도 없고, 그렇다고해도 분명 false sharing은 일어나고 성능 저하가 조금이라도 있어야 하거든요. 아니면 E8xxx 부터는 별도의 스눕 필터링이 들어가서 이런 경우 성능 하락을 막는건지;;

암튼 일단 같은 변수를 업데이트 하는 코드를 먼저 테스트해보세요.. 결과 꼭 알려주세요.
Commented by 조성경 at 2008/05/12 15:11
같은 변수일때도 결과가 같네요. 정확한 테스트를 위해서 코드를 다음과 같이 수정했습니다.

unsigned CALLBACK TestThread1(void* /*arg*/)
{
for (int i = 0; i < 500000000; ++i)
{
_WriteBarrier();
data1 = data1 + 1;
_ReadWriteBarrier();
}

return data1;
}

(DWORD를 unsigned로 수정한것은 제가 _beginthreadex를 사용해서 그렇습니다. 그리고 쓰레드 생성 오버헤드가 있을까 해서 메인을 다음과 같이 수정했습니다)

threads[0] = (HANDLE)_beginthreadex(0, 0, TestThread1, 0, CREATE_SUSPENDED, 0);
threads[1] = (HANDLE)_beginthreadex(0, 0, TestThread2, 0, CREATE_SUSPENDED, 0);

DWORD startTime = GetTickCount();

ResumeThread(threads[0]);
ResumeThread(threads[1]);

제 테스트 결과를 말하면 최악이라는 같은 변수 수정에서도 실행 시간은 같습니다. 두변수의 거리가 0부터 결과는 항상 같습니다. 다른 시스템에서의 결과를 확인해보고 싶네요.
Commented by 조성경 at 2008/05/12 15:15
메모리 쓰기 시점을 강제하기 위해서 _xxxBarrier()를 넣어도 결과에는 영향을 미치지 않네요. 두 변수간에는 어떠한 영향도 없다가 현재의 실험 결과입니다. 이상하네요.
Commented by object at 2008/05/12 16:03
barrier같은 것은 하실 필요가 없어 보입니다. 오히려 그것으로 인한 오버헤드가 커서 false sharing에 대한 효과가 묻힐 수 있습니다. 그리고 당연히 data1에 volatile이나 debug모드로 컴파일 하셨겠지요?
Commented by 조성경 at 2008/05/12 19:40
volatile로 붙여서 빌드했습니다. 어셈결과물을 봐도 실제 계산하는거 맞더군요. barrier는 결과가 달라지지 않아서 혹 영향이 있을까 싶어서 넣어봤습니다만, 영향을 미치지 않네요.

다들 실제 성능에 영향이 있다니 이 간단한걸 잘못 테스트한게 아닐까하는 자괴감이 밀려오군요-_-;;
Commented by object at 2008/05/13 05:16
흐흠.. 신기하네요. E8xxx을 구해서 제가 직접 테스트 해봐야겠네요. 테스트 해주셔서 감사합니다.
Commented by kkamagui at 2008/05/13 07:57
헛.. 저는 1430ms랑 1380ms이면 큰 차이라고 생각했는데... 아닌가 보군요. ;)
두 스레드가 하나의 데이터를 손보도록 수정해도 큰 차이가 없습니다. ^^;;;;
CPU 클럭이 올라갈수록 그렇게 큰 차이가 나지 않는 것은 아닐까요? 그런 생각을 얼핏 한번 해봅니다. ^^;;;
Commented by object at 2008/05/13 08:00
3%도 안 되는 차이니까 큰 차이가 있다고 생각되지는 않습니다. 그리고 정말 듀얼코어 CPU에서 작업하셨는지요? 이 코드의 차이는 듀얼 코어에 적어도 각 코어에 dedicated private cache가 있는 시스템에서만 차이를 유발합니다.
Commented by 조성경 at 2008/05/13 08:47
1430과 1380정도라면 차이가 없다고 보는게 맞습니다. 서너번 실행해서 평균을 내면 차이 0으로 수렴하게 될겁니다.
Commented by kkamagui at 2008/05/14 07:47
그렇군요. ;)
Dual Core 맞고 모델명이 좀 다르네요. ^^;;;;
Core 2 Duo E4500 모델입니다. L1 Cache를 다 별도로 가지고 있고 L2 Cache를 Core 간에 공유하고 있는 모델이지요. ;)
Core가 좋아져서 미연에 방지해 주는 걸까요?
Commented by lojoo at 2008/05/14 11:48
gcc의 __attribute__((aligned(32)) 를 이용하여 위 답글 코드를 테스트해보면 false sharing 문제를 피할 수 없을거 같은데요.. 다만 구조체 s1의 크기만 32로 만들어집니다.
struct의 a,b,c,d의 주소를 찍어보면 아래와 같습니다.
s1.a : 0xfee8f9f0
s1.b : 0xfee8f9f4
s1.c : 0xfee8f9f8
s1.d : 0xfee8f9fc

테스트한 코드입니다.
#define CACHE_LINE 32
#define CACHE_ALIGN __attribute__((align(CACHE_LINE)))

struct CACHE_ALIGN S1 // cache align all instances of S1{
int a, b, c, d;
};
struct S1 s1; // s1 is 32-byte cache aligned

뭐가 잘못된거죠? VC에서는 테스트해보지 못했는데 결과가 다른가요?
Commented by lojoo at 2008/05/14 12:04
자문 자답입니다만.. 구조체 자체에 적용하는게 아니라 구조체 멤버 각각에 _attribute__((align(CACHE_LINE)) 을 적용하니 캐쉬 라인사이즈 만큼 간격을 두고 메모리를 할당하는군여... ㅡㅡ;

Commented by ddudi at 2008/07/02 00:05
false sharing 수정버젼 3078
false sharing 3203


T7200

디버그 버젼에서는 무려 8초정도가 차이나네요;;

좋은 정보 감사합니다.
Commented by object at 2008/07/02 03:12
저도 감사합니다 :)

:         :

:

비공개 덧글

<< 이전 페이지 다음 페이지 >>





by 김민장 2008 이글루스 TOP 100
최근 등록된 덧글
개발자 입장에서의 수많은 ..
by Jiyoon at 02/04
저도 아들 돌잔치때 돌잡이 ..
by 박상욱 at 01/18
미국 대학원 원서 작성중에 p..
by 태클사이야 at 01/13
TO: 박PD 로그인 하지 않아..
by 박응용 at 01/10
http://gigglehd.com/zbx..
by dhunter at 12/28
우와.. 좋네요. 태반이 ..
by 윤광배 at 12/17
항상 좋은 글 잘 보고 있습니..
by y2k at 11/23
글이 좋아서 제 블로그에 담..
by 쏭섭 at 11/23
최근 등록된 트랙백
조엘 스폴스키의 강연 (Sta..
by 인덕원칸타타
[Redis] sds.c를 분..
by 조급하지말고 천천히
메뉴릿
이글루 파인더

website counter

Add to Google

rss

skin by 이글루스