아 오늘 오후엔 일 좀 하려 했는데 자꾸 도발 걸리네.
이번엔 파이프라인과 분기에 대해서 알아보자. (pipeline - 링크)
현대의 CPU들은 명령어를 읽고 해석하고 수행하는 일련의 과정들을 파이프라인으로 세분화해서 처리해. 아키텍처에 따라 파이프라인을 몇단계로 어떻게 나누는가에 따라 다르지만 지금 정리하고자 하는 내용들은 크게 다르지 않으니까, 지금 내가 쓰고 있는 cortex-m3 기준으로 설명할게.
cortex-m3의 파이프라인은 3단계로 구성되어있어. Fetch - Decode - Execute. (링크)
* Fetch - 메모리에서 명령어를 읽어온다.
* Decode - 읽어온 명령어를 해석한다.
* Execute - 해석한 명령어를 실행한다.
간단하게 표현하자면, 컨베이어 벨트에 3명의 작업자가 분업을 하고 있는 상황을 떠올리면 될거야.
Fetch Decode Execute
│ instrA A
│ instrB B A
PC │ instrC C B A
│ instrD D C B
↓ instrE E D C
그림으로 표현하면 위와 같아.
자 그럼 여기서 분기문이 파이프라인에 주는 영향을 보자. instrA가 instrD로의 분기라면 어떻게 될까?
Fetch Decode Execute
│ br D br D
│ instrB B br D
PC │ instrC C B br D
│ instrD D (stalled)
│ instrE E D (stalled)
↓ instrF F E D
요 코드를 컴파일하면 컴파일러가 생성가능한 코드는 다음과 같이 크게 두 가지야. (pseudo code로 표현. 물론 컴파일러와 환경에 따라 table based branch라던지 다른 분기 구조를 가질 수 있음)
condition이 참일때 브랜치 |
condition이 거짓일 때 브랜치 |
branch if(condition == true) to T false_statements ret T: true_statements ret |
branch if(condition == false) to F true_statements ret F: false_statements ret |
수행되는 결과는 둘 모두 같아. 그런데 자세히 보자.
첫번째의 경우는 condition이 true면 분기를 하니까 pipeline이 stall테고,
두번쨰의 경우는 condition이 false면 분기를 하니까 pipeline이 stall되겠지?
그럼 똑같은 코드라 해도 컴파일러가 어떤 분기 구조를 택하는가에 따라 소요되는 클럭싸이클이 달라질 거라는걸 쉽게 예상할 수 있을거야.
자, 이제 그분이 콤마 연산자를 이용해 최적화를 했다고 주장하시는 코드를 한번 보자(링크). 그 분께서 고안하셨대 키키
비교를 위해 디스어셈블 결과도 같이 넣었어. 여기(링크)서 확인하면 될거야.
int test_plain(unsigned int p) { if((p & 0x000000ff)) return 0; if((p & 0x0000ff00)) return 1; if((p & 0x00ff0000)) return 2; if((p & 0xff000000)) return 3; return -1; } |
int test_mo_fuckers(unsigned int p) { int r = -1; if((r = 0, (p & 0x000000ff)) || (r = 1, (p & 0x0000ff00)) || (r = 2, (p & 0x00ff0000)) || (r = 3, (p & 0xff000000))) return r; return -1; } |
| test_plain(unsigned int): xorl x, x testb %dil, %dil jne .L2 testl $65280, i movl $1, x jne .L2 testl $16711680, i movl $2, x je .L8 .L2: rep ret .L8: andl $-16777216, i cmpl $1, i sbbl x, x orl $3, x ret |
test_mo_fuckers(unsigned int): testb %dil, %dil jne .L12 testl $65280, i je .L17 movl $1, x ret .L12: xorl x, x ret .L17: testl $16711680, i jne .L14 andl $-16777216, i jne .L15 movl $-1, x ret .L14: movl $2, x ret .L15: movl $3, x ret |
코드가 똑같진 않지만 대략 연관성 있는 애들끼리 같은 색으로 묶었어.
자. 현명한 프겔러들이라면 이 두 코드의 소요클럭이 다를 때, 어떻게 해석해야 맞는 해석일까? 내가 생각하는 그럴듯한 해석은 '아, 분기가 다르게 구성돼서 파이프라인 스톨 땜에 소요 클럭이 달라졌을 것 같네.'인데, 프겔러들은 어떻게 생각해?
컴파일러 입장에서는 condition이 true일 때가 많을지 false일 때가 많을지 알 수 없을 때 지멋대로 분기가 구성될 때가 많아. 그럼 컴파일러에게 condition이 true일 때가 더 자주 있는지 false일 때가 더 자주 있는지 알려줄 수 있다면 효율적인 코드를 생성하는데 도움이 되겠지?
이 분기 힌트를 어떻게 주는가는 컴파일러마다 다 다른데, boost를 쓰면 cross-platform하게 BOOST_LIKELY(x)나 BOOST_UNLIKELY(x)를 사용할 수 있고(링크), gcc를 쓴다면 리눅스 커널에서처럼 직접 likely(), unlikely()를 디파인해서 쓸 수 있어(링크).
어차피 저 코드는 모든 분기가 같은 확률이라 걍 내 멋대로 분기힌트를 줬는데 생성된 코드를 한번 보자. (링크)
int test_plain(unsigned int p) { if(unlikely(p & 0x000000ff)) return 0; if(unlikely(p & 0x0000ff00)) return 1; if(unlikely(p & 0x00ff0000)) return 2; if(unlikely(p & 0xff000000)) return 3; return -1; } |
int test_mo_fuckers(unsigned int p) { int r = -1; if((r = 0, unlikely(p & 0x000000ff)) || (r = 1, unlikely(p & 0x0000ff00)) || (r = 2, unlikely(p & 0x00ff0000)) || (r = 3, likely(p & 0xff000000))) return r; return -1; } |
test_plain(unsigned int): testb %dil, %dil jne .L3 testl $65280, i jne .L4 testl $16711680, i jne .L5 andl $-16777216, i cmpl $1, i sbbl x, x orl $3, x ret .L3: xorl x, x // return 0 ret .L4: movl $1, x // return 1 ret .L5: movl $2, x // return 2 ret |
test_mo_fuckers(unsigned int): testb %dil, %dil jne .L11 testl $65280, i jne .L12 testl $16711680, i jne .L13 andl $-16777216, i movl $3, x je .L16 rep ret .L16: movl $-1, x // return -1 ret .L11: xorl x, x // return 0 ret .L12: movl $1, x // return 1 ret .L13: movl $2, x // return 2 ret |
흐미 성님 분기힌트만 줬는데 두 코드 분기 구조가 비슷해져부렀소. 콤마연산자를 활용해서 깨알같이 최적화 했는데 이게 어찌된 일이오.
는 무슨 씨발 그냥 저게 최적화가 아닌거지 뭐.
내가 여기까지 썼다면 예상되는 저 새끼의 반응은 '두 코드 생성되는 결과 다르네!! 셀프디스 축하요!!' 요 지랄로 예상한다. 그래서 가져왔어.
이유는 모르겠지만 c++로 컴파일 안하고 c로 컴파일하니까 두 코드가 똑같더라고? 직접 확인해봐. (링크)
생성되는 코드가 같은데 도대체가 뭘 최적화했다고 생각하시는지는 소인은 짬밥이 부족해서인지 잘 모르겠소만, 어쨌든 해보니까 소요 클럭이 다르대더라고??
근데 이 새끼가 뭐라고 해석했는지 한번 살펴보자.
하위 16비트만을 비트 연산할때와 상위 16비트를 계산할때 크게 벌어진다는 것,
즉 super pipeline 단계중, execute 단계에서의 세분화가
word -> byte ( -> bit ? 는 아니겠지 코어 제조 비용이 급증할테니 ㅋㅋ ) 단위로 분기되어 쪼개져 있다는거지.
고로 상위 16bit word의 ( & 0xFFFF0000 ) 연산이 시행되는 시점에서 아얘 0 이면 바로 빠져 나왔고,
그 결과 분기까지의 절차적 거리가 동일하기 때문에 ( 어차피 return 말곤 할게 없음 ),
두 가지 케이스 ( 0x00FF0000 과 0x00000000 의 입력조건 )의 클럭수가 같게 나오는거지.
따라서 비트 연산도 상위 워드는 상위 워드끼리, 하위 워드는 하위 워드끼리 모아줘야
컴파일러의 short circuit 상의 최적화 뿐만 아니라
제대로 super pipeline 상의 short circuit 의 효과를 볼 수 있다는 것.
return code 를 하나로 묶냐 아니냐 에 따라 short circuit 효율 자체가 크게 좌우될 수 있다는 것.
콤마 연산으로 상태를 마킹하고 ( overwrite 만 하기 때문에 writeback+readout 비용은 없음 )
비용이 비싼 연산 앞에 묻어가는 트릭을 말씀드렸슴돠~
하 시발... 워드 바이트 비트로 쪼개지기는 무슨 씨발 네 박자 개소리 위에 쉴새없이 비트를 쪼개는 병신새끼...
여기서 잠깐 정상적인 가설 검증의 루트를 살펴 보자.
1. 가설을 세운다.
2. 관측 한다.
3. 관측 결과가 가설과 안맞으면 1.로 돌아가 새 가설을 세운다.
4. 가설 검증 성공!!
이 가설 검증 루트를 통해 '도대체 저새끼는 왜 저지랄을 떠는가?'에 대한 가설을 세워보기로 했어.
가설1 : 저새끼의 가설 검증 루트가 남들과 다르다. 저 새끼의 가설 검증 루트는 다음과 같을 것이다.
1. 관측한다.
2. 가설을 세운다.
3. 나님은 항상 옳으시다!!
4. 가설 검증 성공!!!
프갤러들아 내 가설이 맞는지 틀린지 다 함께 저 새끼의 행동을 관측해보자.
3줄 요약
* 분기를 하면 pipeline stall 때문에 성능이 저하될 수 있다.
* major 분기를 알 수 있다면 컴파일러에게 분기 힌트를 줘서 효율적인 코드를 생성하게 할 수 있다.
* 근데 사실 이런 테크닉이 realtime 쪽으로 팔 거 아니면 별 쓸데 없음요 ㅋ 그냥 상식삼아 알아두면 돼.
코세가'CISC에서파이프라인이스톨되지않는다'고한적은없는것같은데지금까지
넌 아직 branch hazard 겨우 들어 쳐먹는 수준이고~ 저런 글은 나도 많이 씀유~
더 내부로 들어가면 훨 많은 stall 들이 있지 ㅋㄷ
너한텐 별세계일것이다~
내가 여태껏 얘기한건 '분기가 pipeline stall을 야기한다'라는거야. CISC든 RISC든 상관없다. 근데 저 새끼가 나보고 잘 모른대네? 그래 잘 모를 수 있지. 인정. 근데 내가 뭐 다 안다고 했나? 어쨌든 내가 이 글에서 얘기하고자 하는건 앞 문장에서처럼 '분기가 pipeline stall을 야기할 수 있고 분기구조에 따라 소요 클럭이 다를 수 있다'라는 건데, 그럼 저 새끼도 이 문장은 동의한다고 봐야하는건가?
똑바로 배워라 분기가 pipeline stall 을 야기하는 경우를 branch hazard 라고 한다.
내글 곳곳에 나온다.
이 새끼 또 물타기 하는거봐. 여기서 해저드가 왜 나오냐 병신아 ㅋㅋㅋㅋㅋ 지 불리하면 자꾸 딴거 끌고 물타기 하는건 천성인가벼 ㅋㅋㅋ
자, 그러면 열심히 책보고 branch hazard 의 해결책을 공부해 오렴.
'분기가 pipeline stall을 야기할 수 있고 분기구조에 따라 소요 클럭이 다를 수 있다'라는건명백한사실이죠어떤아키텍쳐건파이프라인을사용한다면요적어도저는그렇게알고있읍니다
어? 이새끼 branch hazard 도 몰라?
뭘 자꾸 깊이 파? 니가 최적화했다는게 사실은 최적화가 아니고 그냥 분기 구조가 달라서 결과가 다르게 나온거라니까?? 뭐 니가 쓰는 컴파일러에서는 더 빠르게 나올 수가 있겠지. 근데 그게 '콤마 연산자에 의한 최적화'가 아니라 그냥 니 컴파일러가 지좆대로 분기구조 만든거에 따른 결과라니까?
브렌치해저드는코세가말한게맞는데
Control hazards (branch hazards)[edit]Further information: branch (computer science) Branching hazards (also known as control hazards) occur with branches. On many instruction pipeline microarchitectures, the processor will not know the outcome of the branch when it needs to insert a new instruction into the pipeline (normally the fetch stage).
자 니가 좋아하는 위키다.
누가 지금 파이프라인 스톨이 왜 어떻게 발생하는지 얘기하자디? 니가 고안하신 '콤마 연산자를 이용한 최적화'에 대한 원인분석이 개소리라니까??
존나 쳐 읽고 아 그게 그거구나 하고 깨달으렴.
하자드가 왜나오냐고? ㅋㄷㅋㄷㅋㄷㅋㄷ
이색 computer architecture 수강한 새끼 맞음?
아이 씨발 이 새끼는 하여튼 말꼬리 잡는거 말고는 할 줄 아는게 없어. 내가 파이프라인스톨이 해저드랑 상관없다고 얘기한거 같냐? 시발 여기서 할 소리가 아니라는거라니까?
아님 수업시간에 쳐 잤냐?
말 돌리지 말고.
sh 도 나랑 똑같이 해석했는데? 니 글을?
야 말꼬리 잡지 말고 본문에 잘못된거 있으면 씨부려봐. 니 의견 받들어서 수정해줄게.
허접티 그만내고 공부좀 더 하고 올래? 넌 아직 멀었어야.
니가 본문에 시부린게 뻘소리라고 ㅉㅉ 병신아. disassemble 한 환경도 내 컴파일러랑 다르고.
이거 봐 이 새끼는 '니 코드는 쓰레기야!' 하지만 근거는 말해주지 않을거다. '넌 공부를 더 하고 와야해!' 하지만 니 글에 뭐가 잘못된건지는 안말해줄거야. 이쯤 되면 길가던 개새끼도 말을 못하는건지 안하는건지 눈치 챌 듯요.
니 주장은 최적화가 아니란거지.
난 저거 클럭 단위로 체크한거거든?
"뭘 자꾸 깊이 파? 니가 최적화했다는게 사실은 최적화가 아니고 그냥 분기 구조가 달라서 결과가 다르게 나온거라니까?? 뭐 니가 쓰는 컴파일러에서는 더 빠르게 나올 수가 있겠지. 근데 그게 '콤마 연산자에 의한 최적화'가 아니라 그냥 니 컴파일러가 지좆대로 분기구조 만든거에 따른 결과라니까?".....컴파일러에세힌트를줌으로써컴파일러가CPU에게전달하는명령어코드를최적화시킬수있게하는게"최적화"의정의가아닌가요?
그러니까 니가 똥싼 '콤마 연산자를 이용한 깨알같은 최적화팁'은 니한테나 적용된다는거 맞냐?
안 통하는 컴파일러도 있지. 근데 니가 data hazard 의 정의와 대책을 안다면, 저게 무용이라고 단정할 순 없지.
data hazard 의 대책이 뭔데? 말해봐.
코세편을드는건아니구요물론저도코세못생겨서좋아하진않읍니다
ㅋㅋ
모든아키텍쳐에서유니버셜하게적용되는최적화기법이그리많치는않은걸로알고있는데요
검색중이니? 검색충아?
ㅇㅇ 저건 미시적 해석임.
너무남의싸움에끼어들었네요미안합니다저는이만일하러
@sh. 그게 저 새끼가 말한 '콤마 연산자에 의한 최적화'가 아니라는거죠. 일단 그걸 지적했던거고, 그리고 결과가 다르게 나온 원인은 저 새끼가 한 개소리가 아니라 분기구조에 따라 달라진 결과라는 걸 얘기하는거예요.
블랙박스 안을 실험을 통해 미시적으로 해석하겠다는거지. 솔직히 내부 비트 표현 순서와 masking 에 따라 처리 속도가 달라지는거 자세히 나와있는 자료 찾기도 힘듦. 차이는 있으니 원인을 추론하는거고.
음?
너 data hazard 도 모르는구나?
검색 덜끝났니?
유니버셜하게 적용되는 최적화 기법은 많죠. 애초에 지금 제가 갖고온 것도 strlen 빠르게 짜려고 워드 단위로 접근하도록 하는 최적화 기법에 해당되는거구요.
딴소리 한다. ㅋㅋ 시간 벌기냐?
computer architecture 똑바로 안들었지? 너
뭐 최적화 기법에 따라 특정 플랫폼에서는 더 느려질 수도 있고(대표적으로 duff's device가 있죠) 한데, 저 새끼가 얘기했던건 그런 레벨의 최적화가 아니란거죠. 거기다 원인 분석도 똥망이구요.
와 개소리 그만하고 data hazard 아냐고
아냐고 임마.
ㅋㅋㅋ 이 새끼 끝까지 본문이랑 다른 얘기하려는거봐. 그래 모른다 치자. 몰라. 근데 뭐? 내가 그걸 모르면 본문글이 뭐가 틀려지니?
난 니 말하는꼬라지들 보면 뭘 모르는지 뭘 안해보고 개소린지 훤히 알겠는데 ㅉㅉ
data hazard 의 대책이 뭔지 공부하고 와.
왜 순서를 재배치하는지.
branch hazard 로 bubble 이 생기기 전에 순서를 바꿔 처리하는게 어떤의민지
왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈왈
이새끼 hazard 도 모르면서 지금껏 최적화 이야기 하는거여?
왜 사냐?
멘탈 나갔냐? 왜 쳐짖냐?
이상 병신만 보면 짖는 개였습니다.
아무나 보고 병신이라고 짖는, unassigned 도 RDTSC 도 hazard 도 pipeline 도 CISC 도 모르는 병신이란거
니가 잘 인증하고 있지.
임마 computer architecture 는 꼭 공부해라.
존나 까이기 싫으면.
unaligned.
제발 좀 까줘. 본문 내용이 어디가 뭐가 틀렸는지 지적해달란 말야. 그래야 나도 잘못 알고 있는거 제대로 알지 않겠어? 라고 해봤자 '니가 알아서 공부해'라는 개소리 말곤 해줄 소리가 없다는거 잘 알고 있단다.
까여도 까인줄 모르는 낙천적인 성격이구나 너 ㅋㄷ
ㅋㅋㅋ 절대 본문에 뭐가 잘못된건지는 얘기 못하지. 할 줄 아는거라곤 '너 이거 알아? 너 저거 알아? 난 아는데!! 공부나 더 해!!' 딸딸이 작작쳐라 뼈 삭는다. 니가 말한것들이 본문에 뭐가 왜 틀렸는지를 얘기하는 뒷받침이나 되냐? 내가 왜 자꾸 너가 물타기 한다고 하는지 모르겠어? 지금 댓글이 100개가 다 되어가는데 너가 말하고자 하는게 뭐야? ㅋㅋㅋㅋ 내가 끝부분에 썼지? '나님은 항상 옳으시다' ㅋㅋㅋㅋ 시발 내 가설이 점점 신뢰도가 높아지고 있다 ㅋㅋㅋ
개소리 계속할거면 고대로 글 긁어서 교수한테 가서 인증받는다? 너 병신인거? 너랑 나랑 신분 까고 해볼래?
ㅋㅋㅋ 이 병신은 꼭 본문이랑 상관없는데서 맴돈대니까 ㅋㅋㅋㅋ 에휴
이 분 비쥬얼스튜디오한테 신분증 들이밀고 컴파일 부탁하실 분
본문, 댓글갖고 교수한테 간다는건데 난독증인가. 띨빡아.
그래. 그렇게 해. 안말릴게. ㄱㄱ. 내가 틀린거면 내가 틀려서 좋고, 내가 맞는거면 니가 정신차려서 좋고 그렇지 뭐. 해. ㄱㄱ
일단 둘이 신분부터 까고.
수고끼치는 보상은 철저히 해줄게.
수고끼치는 보상은 철저히 해줄게.
KLDP에서도 엄청 까인 사람과 뭘 이야기를 하나요? 그냥 무시해버리셈. 이런 애들은 그냥 무시하는게 답
이거 봐 이 새끼 어디 어느 교수님한테 가는지는 모르겠는데 그거랑 신분까는 거랑 무슨 상관이여 ㅋㅋㅋㅋㅋ 진짜 하나하나 말 돌리는데 기가 찬다 기가 차
미안하지만 난 KLDP 에 글싼적 없소만.
난 내가 절대 근거없는 뻘짓한거 아닌게 옳으니깐, 틀린쪽이 갤에 실명 공개하자고 왜? 떫음? 자신 없음?
쥐좆도 모르는 새끼가 지 할 공부는 안하고 남 물고늘어지는거 아주 혼쭐을 내주지.
왜, 니가 근거없이 사람 매도한거 다 합치면 고소감 아닐것 같아?
이건 뭐 제대로 설명해도 우기기나 하고 지는 아무것도 대답 못하고, 서로가 옳다는 주장을 검증 받고 실명까자고. 됐냐?
이봐 덤빌려면 똑바로 알고 덤벼. 뭐 같지도 않은 검색충 주제에. 시발 안쪽팔리냐? computer architecture 도 모르는새끼가.
허허 웃으면서 대해주니까 아주 이게 미쳐가지고. ㅉ
내가 지금껏 그나마 참은건, 갤에 니가 쓰는 글을 좋아하는 애들이 있기 때문이야. 정신차려.
같은거 두 번 설명하는것도 짜증나는데 넌 나한테 몇 번을 설명하게 했는지 아냐? 어? 니가 틀린것들로.
첨에 니가 나더러 병신이라고 했을때도, 내가 너한테 뭐 해꼬지 한게 있든? 없었지?
4일동안 있었던 대화 고스란히 들고가서 점검받자. 멍청한 새끼야. 라인 바이 라인으로 아주 탈탈 털어줄께.
지랄 싸고 자빠졌네. 실명 까면 뭐 틀린게 맞고 맞는게 틀린게 되냐? 내가 말돌리지 말랬지? 씹쌔끼가 할말 없으니까 실명을 까재. 자꾸 쓸데없이 빙빙 돌지말고 니 주장에 대한 근거나 마련해. 이 새끼는 지 주장에 근거도 못대면서 주둥이만 좆나 털어. 내가 애초에 니한테 요구한게 뭐였어? 니 조잡한 경험 말고 객관적인 근거를 가져와서 얘기하랬지? 니가 레퍼런스 들고 오면 인정한대니까? 븅신새끼가 들고 오라는 레퍼런스는 안들고오고 점점 더 좆같은 소리만 늘어놓네. 내가 괜히 '나님은 항상 옳으시다'가설을 세운게 아니라니까 씨발.
하하. 근거는 저 글 쓰기 전에 다 준비되어 있었고
니가 unaligned 에 대해 헛소리하기 전에 모든 데이터를 다 갖고 있었음.
니가 나한테 지랄을 할라믄 '이거 알아? 저거 알아?' 이지랄할게 아니라 내 본문의 어느 내용이 어디가 왜 틀렸고 그게 틀렸음을 입증할 수 있는 객관적인 자료야 병신아. 이 새끼는 인터넷 자료들도 다 좆병신이고 지 혼자 맞다고 생각하네. 그니까 인터넷이든 뭐든 가져오든가 니가 교수한테 가서 맞는지 틀린지 의견을 받아오던가 하라고. '갈까? 갈까?' 이지랄 좀 고만싸고 진짜로 좀 가서 입증을 받던가 가져오던가 하고 씨부려 븅신새끼야
가설이고 나발이고 아니라, codesafer@gmail.com 으로 전화번호 보내라. 아주 둘이 만나서 교수한테 가자.
주둥아리 그만 털고 니 경험 말고 뭐든 좀 들고 와서 얘기해라. 그 때까진 그냥 개소리로 받아들이고 있을테니.
그딴거 다 필요 없음. 왠지 앎?
어지간한 엔지니어나 교수들은 그거 다 알고 있는 사실이거든.
니가 웹에서 참조하는 아티클 같은 건 나같은 사람들이 쓰는거야 바보야.
이멜로 전화번호 보내라. 나도 바로 보내지. 교수한테 가면되지. 니 항변할 자료는 알아서 모아두시고.
난 4일간 대화내용만 캡쳐하면됨.