새소게에서 64비트 ARM 관련 얘기만 나오면 논란이 많은데요, 이 부분 정리 해 드리겠습니다.
일단 간단하게 제 소개를 드리자면 :
16년간 ARM 어셈블리만 해 온 최적화의 달인 암빠... 입니다.
16년은 아니고 ARM을 처음 접한지 정확히 11년 째네요. 그 한참 전에는 모토롤라 MC68k 시리즈로 작업 했고요.
현재는 이학렬 기자와 비슷한 처지입니다. 안드로이드로 돈 벌어서 아이폰이랑 맥북 사서 씁니다.
ARM의 64비트 전향을 한 단어로 요약하면 : 할렐루야
그럼 왜 그런지, (알고 그러는지 모르고 그러는지) 몇몇 분들이 퍼뜨리는 루머만 반박하면 간단하게 설명 가능합니다.
- 64비트 CPU가 32비트로 동작하면 에뮬레이션이라서 32비트 CPU보다 느리다 :
ARM은 아닙니다. 32비트 모드가 존재하지만 에뮬레이션이 아니라 전용 네이티브 모드입니다.
더군다나 파이프라인 유닛이 향상되어 64비트 v8이 32비트 모드에서 동클럭 v7보다 빠릅니다.
- 64비트는 앞으로는 몰라도 당장은 큰 의미가 없다 :
앱 개발자가 OS 최소 사양을 7 미만으로 설정하여도 v7/v8 하이브리드 바이너리가 생성된다면 이건 100% 틀린 말이고요 (앱 개발 손 뗀 지 좀 되어서 확인 불가능하니 현역이신 분 댓글로 답변 주시기 바랍니다) 그렇지 않다 하여도 반도 안 맞는 얘기입니다.
전자인 경우 iOS7 출시 이후 업데이트 된 앱이라면 5s에서 100% 64비트로 동작하고, 후자인 경우라도 64비트로 구현 된 웹킷 및 기본 OS 컴포넌트/프레임웍들의 잇점을 톡톡히 보게 됩니다. 더더군다나 HTML5로 작성 된 앱이라면 두 말 할 것도 없습니다.
- 64비트 전향이 애당초 퍼포먼스상 큰 잇점이 없다. 64비트 윈도우 보면 4기가 이상 사용 가능한 것 말고 무엇이 있는가 :
RISC와 CISC에는 큰 차이가 있습니다. RISC상에서는 CISC와 달리 레지스터 갯수가 엄청 중요한데 너무 깊게 내려가면 이해하시기 힘들테니 간단히 예를 들어보겠습니다.
고학생 출신 R군과 유복한 집의 C군이 인턴사원으로 입사 합니다. 월급은 160만원.
월급이 같다고 둘의 생활 수준이 같을까요? 그럴 리 없겠죠?
R군은 월급에서 세금, 4대보험, 교통비, 중식비등을 공제한 나머지 돈으로 학자금 대출 상환, 식비, 임대료 등 생활과 관련된 모든 것을 해결해야 합니다. 엄청 빡빡하죠.
반면 C군에게는 기본공제를 제외한 전체 금액이 그야말로 용돈입니다. 학자금 대출은 애당초 없고 숙식은 부모님이 해결 해 줍니다.
세월은 흘러 두 사람 다 인턴과정을 마치고 정사원으로 채용 됩니다. 급여도 320만원으로 인상되고요.
C군에게 급여인상은 큰 의미가 없습니다. 급여가 인상되었으니 부모님께서 용돈/생활비를 달라 하셔서 실제 굴릴 수 있는 돈은 인턴 시절과 별 차이가 없습니다.
반면 R군은 드디어 고생 끝 행복 시작입니다. 급여인상 이전과 동일한 생활수준을 유지한다면 월별 유용금액은 단순 두 배가 아니라 네다섯 배로 껑충 뛰는 것입니다.
이게 바로 RISC와 CISC의 차이입니다. ARMv8에서 레지스터 갯수가 16개에서 32개로 증가했는데, 이는 어마어마한 차이입니다.
ARM의 발전 과정을 보면 다음과 같습니다
ARMv5E (ARM9) : DSP 명령어 추가. 16비트 연산으로 속도 및 레지스터 효율 향상
ARMv6 (ARM11) : SIMD 유사 명령어 추가. 레지스터 부족으로 효율은 제한적임. VFP(FPU)추가.
ARMv7 (Cortex A8, A9, A15) : 비트 연산 명령어 추가. 듀얼/트리플 이슈 추가. 레지스터 부족으로 극도로 제한적인 성능 향상. NEON (SIMD) 추가
ARMv8 (Cortex A53, A57) : 64비트 명령어 풀셋 추가. 레지스터 갯수 2배(ARM 32개, NEON 64개)
요약하자면 CISC와 달리 RISC에서는 레지스터가 부족하여 그간 꾸준히 이루어진 아키텍쳐의 향상된 기능들이 극히 제한적인 성능 향상만을 가져왔다는 것입니다. 그런데 레지스터가 두 배가 되니 실제 가용 레지스터는 네다섯배로 껑충 뜁니다.
즉, 레지스터 부족으로 인한 고질적인 병목현상이 완전히 해소되는 것으로, 그야말로 봉인이 풀리는 수준의 성능향상이 나옵니다.
반면 여기서 NEON은 좀 다른데요, v7에서 32개의 NEON레지스터는 대부분의 경우 부족하지 않습니다.
즉, NEON에 의존적인 루틴들은 상대적으로 v8에서 성능향상이 거의 없다고 볼 수 있지만 두 가지 예외가 있습니다 : DCT와 Image Processing입니다.
8x8 DCT Type II는 (일명 iDCT) jpeg과 동영상 디코딩시 반드시 필요하고, 데이터 사이즈 대비 연산량이 어마어마한 루틴입니다.
32개의 레지스터는 부족하여 트랜스폼을 가로로 한 번 하여 중간 저장하고 이를 가지고 세로로 처리하여 최종 결과물을 만들어 내는데요, 64개의 레지스터로는 이를 한 큐에 처리 할 수 있게 됩니다. 각종 벤치에서 보듯이 jpeg과 동영상에서 상당한 수준의 성능향상이 나타남은 물론 중간 저장 과정이 생략되는 만큼 전력소모도 크게 줄어듭니다. (메모리 RW가 전력소모가 큽니다)
또한 32개의 레지스터로는 3x3까지의 이미지 필터만 싱글패스로 가능했는데 64개라면 9x9까지도 싱글패스 처리 가능합니다. 예를 들어 일명 뽀샤시로 통하는 5X5 Gaussian Blur쯤은 완전 껌으로 FHD 해상도 카메라 프리뷰 실시간 처리 가능합니다.
한 줄 요약 : 모바일에서 64비트와 32비트의 차이는 어마어마하다. 몇 푼 아끼자고 5S대신 5C를 구매하는 것은 치명적인 실수이다.
아이폰 싫증나서 넥서스5 나오면 갈아타려 했는데 5S가 64비트로 출시되는 바람에 계획이 무산되었네요. 어서 25일이 와서 문서로만 보던 64비트 명령어 실제로 써보고 싶습니다. (개발자 프로그램 리뉴얼 해야겠네요)
아이러니하게도 아이폰에서 안드로이드용 64비트 코드 구현하게 생겼습니다.
내년에는 자칫하면 64비트 기기에 32비트 안드로이드 탑재되어 출시되는 엽기적인 상황이 연출 되겠네요.
밥벌이 차원에서라도 그러지 않기를 바라지만 안드로이드는 너무 복잡하게 이해관계가 얽혀있어서 내년 가을 넥서스 신모델 쯤 되어서야 64비트로 전향하지 싶습니다.
내용 추가 :
자고 일어나서 접속했더니 완전 흥하는군요.
서정우님 지적하신대로 명령어 인코딩은 32비트가 맞습니다. 지적 감사합니다.
내킨 김에 밀린 숙제 하는 기분으로 v8 명령어를 익혔는데 일단 꽤 실망스럽습니다. 제 소감은 이렇습니다 :
+ 32비트 레지스터 32개, 혹은 64비트 16개가 아니라 64비트 32개임. 따라서 레지스터 용량은 두 배가 아니라 네 배임
+ 메모리 관련 명령어들이 영리해짐 ==> 캐쉬 효율 상승
- conditional execution, inline barrel shifter 대폭 하향
- v5E, v6, v7을 거치며 추가된 명령어들 대부분 칼질 당함
- SIMD식 처리 지원 없음
1 LDR r6,[r1],#4 SUBS r10,r10,#1
1 LDR r4,[r2],#4
1i
2 LSR r3,r6,#24 UBFX r8,r6,#8,#8
2 UBFX r9,r4,#16,#8 RSB r12,r3,#0xff UBFX r11,r6,#16,#8
2 MUL r9,r9,r12 UBFX r7,r4,#8,#8 UXTB r6,r6
2 MUL r7,r7,r12
1 STR r6,[sp,#4]
0 *UXTB r6,r4 LSR r4,r4,#24
2 MLA r9,r3,r11,r9
2 MLA r7,r3,r8,r7
2 MUL r6,r6,r12
3 UMULL r8,r9,r5,r9
1 LDR r8,[sp,#4]
2 MUL r4,r4,r12
3 UMULL r12,r7,r5,r7 LSR r9,r9,#7
2 MLA r6,r3,r8,r6
2 MLA r3,r3,r3,r4
1i
1 LSL r9,r9,#16 LSR r7,r7,#7
3 UMULL r12,r6,r5,r6 ADD r7,r9,r7,LSL #8
3 UMULL r8,r3,r5,r3
2i
2 ADD r6,r7,r6,LSR #7 LSR r3,r3,#7
2 ADD r3,r6,r3,LSL #24
1 STR r3,[r0],#4
멀티플 이슈 가능한 부분 전부 한 라인으로 처리했고, 앞의 숫자가 라인당 소요 사이클입니다.
i로 시작하는 라인은 인터락입니다. 해저드라고도 합니다.
0이 붙고 * 처리한 라인은 OOE(Out of Order Execution)에 의하여 그 전 라인에 꼽사리 끼여서 처리 가능한 파트입니다. 딱 한 군데 있군요. 그나마 컴파일러가 똑똑했다면 아예 발생 안 했을겁니다.
루프 1회당 1픽셀만 처리하며, 레지스터가 부족하여 언롤링 불가합니다. 46 사이클 소요합니다.
어셈블리 프로그램 해 보면 느끼지만 OOE야말로 실제로 별 도움이 안 되는 기능입니다.
중간에 메모리 저장 명령어가 있으면 그 후 따라오는 어떤 메모리 관련 명령어 및 이와 연관된 명령어들을 그 앞으로 댕겨오지 못 합니다.
간단한 함수라면 어차피 언롤링을 통하여 다중실행 증가 및 인터락 감소를 도모 할 수 있으니 쓸모가 없고 타이트한 상황에서는 레지스터가 부족하여 전혀 도움이 안 됩니다.
다음은 인간 컴파일러가 작성한 동일한 기능을 하는 v8 코드입니다 (스압 주의) :
ldnp | x4,x6,[x1],#16 | subs | w3,w3,#8 | ||
ldnp | x5,x7,[x2],#16 | ubfx | w15,w4,#24,#8 | ubfx | w12,w4,#0,#8 |
ldnp | x8,x10,[x1],#16 | ubfx | w13,w4,#8,#8 | ubfx | w14,w4,#16,#8 |
ldnp | x9,x11,[x2],#16 | rsb | w29,w15,#255 | ubfx | w16,w5,#0,#8 |
mul | w13,w13,w15 | ubfx | w17,w5,#8,#8 | ubfx | w18,w5,#16,#8 |
mul | w14,w14,w15 | ubfx | w19,w5,#24,#8 | ubfx | x23,x4,#56,#8 |
mul | w15,w15,w15 | ubfx | x20,x4,#32,#8 | ubfx | x21,x4,#40,#8 |
mul | w12,w12,w15 | ubfx | x22,x4,#48,#8 | rsb | w28,w22,#255 |
mla | w12,w16,w29,w12 | ubfx | x24,x5,#32,#8 | ubfx | x25,x5,#40,#8 |
mla | w13,w17,w29,w13 | ubfx | x26,x5,#48,#8 | ubfx | x27,x5,#56,#8 |
mla | w14,w18,w29,w14 | ||||
mla | w15,w19,w29,w15 | ||||
mull | x12,w12,w30 | ||||
mull | x13,w13,w30 | ||||
mull | x14,w14,w30 | ||||
mull | x15,w15,w30 | ||||
mul | w20,w20,w23 | ubfx | x12,x12,#32,#8 | ubfx | x13,x13,#32,#8 |
mul | w21,w21,w23 | ubfx | x14,x14,#32,#8 | ubfx | x15,x15,#32,#8 |
mul | w22,w22,w23 | ubfx | w15,w6,#24,#8 | ubfx | w12,w6,#0,#8 |
mul | w23,w23,w23 | ubfx | w13,w6,#8,#8 | ubfx | w14,w6,#16,#8 |
mla | w20,w24,w28,w20 | rsb | w29,w15,#255 | ubfx | w16,w7,#0,#8 |
mla | w21,w25,w28,w21 | ubfx | w17,w7,#8,#8 | ubfx | w18,w7,#16,#8 |
mla | w22,w26,w28,w22 | ubfx | w19,w7,#24,#8 | ||
mla | w23,w27,w28,w23 | ||||
mull | x20,w20,w30 | ||||
mull | x21,w21,w30 | ||||
mull | x22,w22,w30 | ||||
mull | x23,w23,w30 | ||||
mul | w13,w13,w15 | ubfx | x20,x20,#32,#8 | ubfx | x21,x21,#32,#8 |
mul | w14,w14,w15 | ubfx | x22,x22,#32,#8 | ubfx | x23,x23,#32,#8 |
mul | w15,w15,w15 | orr | w24,w12,w13,lsl #8 | orr | w25,w14,w15,lsl #8 |
mul | w12,w12,w15 | orr | w26,w20,w21,lsl #8 | orr | w27,w22,w23,lsl #8 |
mla | w12,w16,w29,w12 | orr | w4,w24,w25,lsl #16 | orr | w5,w26,w27,lsl #16 |
mla | w13,w17,w29,w13 | ubfx | x23,x6,#56,#8 | ubfx | x20,x6,#32,#8 |
mla | w14,w18,w29,w14 | ubfx | x21,x6,#40,#8 | ubfx | x22,x6,#48,#8 |
mla | w15,w19,w29,w15 | rsb | w28,w22,#255 | ubfx | x24,x7,#32,#8 |
mull | x12,w12,w30 | ubfx | x25,x7,#40,#8 | ubfx | x26,x7,#48,#8 |
mull | x13,w13,w30 | ubfx | x27,x7,#56,#8 | ||
mull | x14,w14,w30 | ||||
mull | x15,w15,w30 | ||||
mul | w20,w20,w23 | ubfx | x12,x12,#32,#8 | ubfx | x13,x13,#32,#8 |
mul | w21,w21,w23 | ubfx | x14,x14,#32,#8 | ubfx | x15,x15,#32,#8 |
mul | w22,w22,w23 | ubfx | w15,w8,#24,#8 | ubfx | w12,w8,#0,#8 |
mul | w23,w23,w23 | ubfx | w13,w8,#8,#8 | ubfx | w14,w8,#16,#8 |
mla | w20,w24,w28,w20 | rsb | w29,w15,#255 | ubfx | w16,w9,#0,#8 |
mla | w21,w25,w28,w21 | ubfx | w17,w9,#8,#8 | ubfx | w18,w9,#16,#8 |
mla | w22,w26,w28,w22 | ubfx | w19,w9,#24,#8 | ||
mla | w23,w27,w28,w23 | ||||
mull | x20,w20,w30 | ||||
mull | x21,w21,w30 | ||||
mull | x22,w22,w30 | ||||
mull | x23,w23,w30 | ||||
mul | w13,w13,w15 | ubfx | x20,x20,#32,#8 | ubfx | x21,x21,#32,#8 |
mul | w14,w14,w15 | ubfx | x22,x22,#32,#8 | ubfx | x23,x23,#32,#8 |
mul | w15,w15,w15 | orr | w24,w12,w13,lsl #8 | orr | w25,w14,w15,lsl #8 |
mul | w12,w12,w15 | orr | w26,w20,w21,lsl #8 | orr | w27,w22,w23,lsl #8 |
mla | w12,w16,w29,w12 | orr | w6,w24,w25,lsl #16 | orr | w7,w26,w27,lsl #16 |
mla | w13,w17,w29,w13 | ubfx | x23,x8,#56,#8 | ubfx | x20,x8,#32,#8 |
mla | w14,w18,w29,w14 | ubfx | x21,x8,#40,#8 | ubfx | x22,x8,#48,#8 |
mla | w15,w19,w29,w15 | rsb | w28,w22,#255 | ubfx | x24,x9,#32,#8 |
mull | x12,w12,w30 | ubfx | x25,x9,#40,#8 | ubfx | x26,x9,#48,#8 |
mull | x13,w13,w30 | ubfx | x27,x9,#56,#8 | ||
mull | x14,w14,w30 | ||||
mull | x15,w15,w30 | ||||
mul | w20,w20,w23 | ubfx | x12,x12,#32,#8 | ubfx | x13,x13,#32,#8 |
mul | w21,w21,w23 | ubfx | x14,x14,#32,#8 | ubfx | x15,x15,#32,#8 |
mul | w22,w22,w23 | ubfx | w15,w10,#24,#8 | ubfx | w12,w10,#0,#8 |
mul | w23,w23,w23 | ubfx | w13,w10,#8,#8 | ubfx | w14,w10,#16,#8 |
mla | w20,w24,w28,w20 | rsb | w29,w15,#255 | ubfx | w16,w11,#0,#8 |
mla | w21,w25,w28,w21 | ubfx | w17,w11,#8,#8 | ubfx | w18,w11,#16,#8 |
mla | w22,w26,w28,w22 | ubfx | w19,w11,#24,#8 | ||
mla | w23,w27,w28,w23 | ||||
mull | x20,w20,w30 | ||||
mull | x21,w21,w30 | ||||
mull | x22,w22,w30 | ||||
mull | x23,w23,w30 | ||||
mul | w13,w13,w15 | ubfx | x20,x20,#32,#8 | ubfx | x21,x21,#32,#8 |
mul | w14,w14,w15 | ubfx | x22,x22,#32,#8 | ubfx | x23,x23,#32,#8 |
mul | w15,w15,w15 | orr | w24,w12,w13,lsl #8 | orr | w25,w14,w15,lsl #8 |
mul | w12,w12,w15 | orr | w26,w20,w21,lsl #8 | orr | w27,w22,w23,lsl #8 |
mla | w12,w16,w29,w12 | orr | w8,w24,w25,lsl #16 | orr | w9,w26,w27,lsl #16 |
mla | w13,w17,w29,w13 | ubfx | x23,x6,#56,#8 | ubfx | x20,x6,#32,#8 |
mla | w14,w18,w29,w14 | ubfx | x21,x6,#40,#8 | ubfx | x22,x6,#48,#8 |
mla | w15,w19,w29,w15 | rsb | w28,w22,#255 | ubfx | x24,x7,#32,#8 |
mull | x12,w12,w30 | ubfx | x25,x7,#40,#8 | ubfx | x26,x7,#48,#8 |
mull | x13,w13,w30 | ubfx | x27,x7,#56,#8 | ||
mull | x14,w14,w30 | ||||
mull | x15,w15,w30 | ||||
mul | w20,w20,w23 | ubfx | x12,x12,#32,#8 | ubfx | x13,x13,#32,#8 |
mul | w21,w21,w23 | ubfx | x14,x14,#32,#8 | ubfx | x15,x15,#32,#8 |
mul | w22,w22,w23 | orr | x4,x4,x5,lsl #32 | orr | x5,x6,x7,lsl #32 |
mul | w23,w23,w23 | ||||
mla | w20,w24,w28,w20 | ||||
mla | w21,w25,w28,w21 | ||||
mla | w22,w26,w28,w22 | ||||
mla | w23,w27,w28,w23 | ||||
mull | x20,w20,w30 | ||||
mull | x21,w21,w30 | ||||
mull | x22,w22,w30 | ||||
mull | x23,w23,w30 | ubfx | x20,x20,#32,#8 | ||
stnp | x4,x5,[x0],#16 | ubfx | x21,x21,#32,#8 | ubfx | x22,x22,#32,#8 |
ubfx | x23,x23,#32,#8 | orr | w24,w12,w13,lsl #8 | orr | w25,w14,w15,lsl #8 |
orr | w26,w20,w21,lsl #8 | orr | w27,w22,w23,lsl #8 | orr | w10,w24,w25,lsl #16 |
orr | w11,w26,w27,lsl #16 | orr | x6,x8,x9,lsl #32 | ||
orr | x7,x10,x11,lsl #32 | ||||
stnp | x6,x7,[x0],#16 |
레지스터가 넉넉하여 루프 1회당 8픽셀 처리합니다. 제로 인터락에 OOE는 전혀 불필요합니다. (ARM빠이지만 ARM에서 그렇게 내세운 OOE에 대해선 회의적입니다)
루프 1회당 210 사이클 소요하는데, 공식 자료가 없는 관계로 추정치입니다. 5S 있으면 테스트 해 보겠는데 갑갑하네요.
이보다 더 소요한다면 최대 32사이클 늘어나고, 제가 희망하는게 맞다면 100사이클가량 줄어듭니다.
추정치인 210사이클을 기준으로 계산 해 보면 46/(210/8) = 1.752...
대략 75% 가량의 성능 향상이 있을테고, 여기에 추가로 캐쉬 버프가 발생하므로 대략 90%가량의 성능향상이 있으리라 봅니다.
몇몇 분들이 정말로 궁금해 하시는건지, 아니면 트집 잡으려 그러는건지 자꾸 64비트라서 덕을 본게 얼만큼이냐 하시는데, 그에 대한 제 답변은 다음과 같습니다 :
- 늘어난 레지스터의 잇점 : 공격적인 언롤링 가능=>인터락 제로, 다중실행 증가 및 캐쉬 효율 상승
- 신형 아키텍쳐상의 잇점 : 캐쉬 힌팅 메모리 명령어
- 64비트의 잇점 : 메모리 RW 2배속, 32비트 long 곱셈 명령어 2배속, 넓은 레지스터로 인한 효율 상승/추가 언롤 => 인터락, 다중실행, 캐쉬 관련 성능 향상
전체적인 관점에서 레지스터 갯수가 늘어난 것이 아키텍쳐상의 잇점이라 칠 때 64비트가 가져오는 잇점과 얼추 비슷한 것으로 보입니다.
캐쉬라는 것이 워낙에 며느리도 모르는 별개의 생명체인지라 구체적인 수치화는 불가능합니다.
5S 수령하면 실제 벤치마크 구동하여 내용 추가하거나 새로 글 올리겠습니다.
PS : 상기 64비트 코드는 문서만 보고 손으로 작성한 것이므로 오류의 가능성이 높습니다. 그러나 전체적인 카운팅에는 큰 차이가 있을 수 없습니다.
"64비트 CPU가 32비트로 동작하면 에뮬레이션이라서 32비트 CPU보다 느리다"
이 부분은 단순 64비트(32비트)호환 플랫폼의 특성이 네이트브 32비트보다 빠르다는게 아니라 기존의 32bit ARM코어보다 새로나온 칩이 강화되어 빠르다라고 느껴지네요.(동일 코어를 사용했을대 32bit보다 64bit에서 32bit를 지원하는게 더 빠르다면 32bit 프로세서를 안만들고 64bit만 생산하겠죠.. 단가도 문제긴 하지만..)
v6까지는 16개의 레지스터로 그럭저럭 버텼지만 v7부터 추가된 멀티이슈 기능이 레지스터가 부족하여 별 효용이 없었습니다. 듀얼까지는 간혹 재미를 봤지만 A15의 트리플은 거의 무의미했거든요.
레지스터야 다다익선이지만 16개에서 32개로의 상향은 하늘과 땅 차이입니다.
어느 정도냐면 특성상 네온 프로그래밍이 더 어려워야 정상인데 v7에서도 네온은 레지스터가 32개거든요. 레지스터가 넉넉하다보니 네온 프로그래밍이 ARM보다 월등히 쉽습니다.
레지스터의 개수 증가를 위해서는 64bit 명령어셋의 추가가 선행되어야만 사용 가능한건가요?
그리고 아난드텍에서 한 벤치에서는 정확하게 어떻게 측정했는지는 모르겠지만 JPEG 압축/압축해제 모두 10%정도의 성능향상만 있었습니다. 생각보다 드라마틱하지 않다고 생각하는데, 어떻게 생각하시나요?
http://www.anandtech.com/show/7335/the-iphone-5s-review/4
그리고 아난드텍 차트는 integer 코어 테스트라서 NEON을 사용하지 않은 것으로 알고 있습니다.
'명령어' 크기는 32bit 그대로입니다. 별 쓸모없던 '조건부실행'을 없애서, 비트 확보하고, 명령어 재구성했죠.
SIMD 레지스터는 32개 '그대로'입니다. 단, 기존에는 '64bit'레지스터였고, 128bit 의 '가상레지스터'(라고 하겠습니다. 제멋대로)를 64bit 레지스터 '두개'를 묶어서 사용하여 16개 였었지만, v8 에서는 128bit 레지스터가 32개가 되었습니다.
(128bit 를 열심히 활용하면 16->32로 '두배'입니다만, 64bit 레지스터는 32개 그대로인거죠.)
그렇다면 레지스터가 추가되었다기보다는 레지스터가 커졌다고 보는게 맞는건가요?
64bit를 초과하는 데이터가 사용될때 레지스터의 비효율성을 줄였다 정도?
64bit 명령어셋 덕분에 성능향상이 아니라 32bit 명령어를 재구성한 덕분에 성능향상이 있다 인건가요?
초기에 64bit 32개...로 만들었다가 이후에 128bit 를 넣으면서 레지스터를 안늘리고 땜빵했던거죠.
(또한, 변환관련 명령어를 추가하지않고, 64bit 처리 128bit 처리를 왔다갔다 할 수도 있구요.(64bit 로 처리한 두개를 이후에 바로 128bit 처리를 할 수 있는 등의...))
하지만, 이렇게 땜빵해서, 128bit 처리시에 레지스터가 부족하게 되었던 것이고...
그걸 이번에 32개로 늘린거죠.
(대신, 64bit 와 128bit 명령어간에 데이터를 주고받으려면 일종의 변환이 필요하게 되었고요.
(기존에는, d(n*2), d(n*2+1) 레지스터가, q(n) 레지스터로 되어서, 128bit 의 하위, 상위 값을 바로 64bit 명령어로 처리, 64bit 명령어로 처리된 데이터 두개를 연속레지스터에 넣고 바로 128bit 처리...가 되었지만, 이제는 다른 레지스터로 옮겨줘야하죠.)
그래서, 128bit 에서 레지스터 두배...가 된건 중요한겁니다.
그럼 결론은...
64bit 명령어셋이 들어온 덕택이라기보다는 레지스터의 크기가 두배 커진게 성능향상의 주요한 영향이다. 이런건가요???
하드웨어 구조 개선
(ARMv7 코드(기존 32비트 코드) 성능개선에 영향)
ARMv8의 레지스터 증가와 명령셋 개선
(ARMv8 지원하도록 '재컴파일'한 코드의 성능개선에 영향, 단 포인터는 기본적으로 64비트로 늘어나, 포인터를 많이 쓰면 상대적 성능저하 발생 가능)
64bit
(실제 64bit '값'을 사용하는 코드에 영향)
기타 부가기능(특정 암호화 지원 명령어등)
(해당 기능을 사용하는 특정 작업에 영향(물론 이에 맞춰 새로 작성된 경우))
의 적용 수준에 따른 복합적인 결과죠.
그렇다면 실제 32bit코드의 성능향상은 어느부분에서 주로 일어난거라고 볼 수 있는건가요?
FPU의존적 어플리케이션에서 폭발적인 성능향상이 일어난 경우가 일부 있는 것은 128bit 레지스터의 효과인 것으로 보이고...
ALU쪽에서의 일부 성능향상이 있는 어플리케이션들은 128bit 레지스터의 효과와 명령어셋 개선 덕택인걸까요?
결국 64bit 명령어셋의 지원은 32bit 어플리케이션에서 큰 영향을 주지 못한다는 말씀인걸까요?
32bit 코드가, '기존의 컴파일된 코드'를 말씀하시는건지 '새로 컴파일하는 소스 코드'수준에서 말씀하시는것인지 불명확 합니다만...
앞의 경우는, Pentium 4 에서 Core 2 시리즈로 올때 내부 개선으로 차이가 나고, Core 2 계통에서도 세대가 바뀌면서 pipe 증가등으로 향상시키는 등의... 내부 구조개선 영향이로 바뀌는 것이구요.
뒤의 경우 64bit 데이터를 전혀 사용안하는 경우라면, 명령셋 변경으로인한 개선(명령셋 자체와 하드웨어의 처리)과 레지스터 증가로 인한 효율향상에서, 포인터크기 증가로 인한 손실...을 빼야 하는거죠.
(물론, 포인터값이 메모리에 있어야 하는 경우에만 손실이 있습니다.)
많은 말씀 감사드립니다^^ 이해하는데 도움이 되었어요.
애초 RISC로 설계된 CPU에 비해 명령어 디코더 부분이 비대해지는 단점이 있지만, 이후 실행유닛은 별 차이가 없다는 이야기죠.
그리고 '64비트이기 때문에' 레지스터 갯수가 늘어나는 게 아닙니다. 새로운 아키텍쳐이기 때문에 늘어난 거죠.
새로운 아키텍쳐로 인한 향상(새로운 아키텍쳐를 도입하게 된 데에는 64비트로의 전환이 주요한 계기가 되기는 했지만)을 왜 64비트의 이점으로 소개하고 계시는지요?
32비트를 그대로 유지하면서 레지스터의 갯수를 늘렸다면 - 지금 상황에서 ARM이 그런 선택을 할 이유는 별로 없었겠지만 만약에라도 - 예로 드신 작업에서의 장점은 사라지는 것입니까?
addeq r0, r1, r2, lsr r3
위 명령어를 보시면 레지스터 네 개입니다. 총 레지스터가 16개이니 각각 4비트고요, condition code 4비트, barrel shifter 4비트 등을 합하면 이미 24비트입니다. 명령어 자체는 용으로는 8비트가 남죠. 만약 레지스터가 32개였다면 5비트씩 할당해야 하므로 명령어 용으로는 딸랑 4비트가 남습니다.
UAL로 통합되면서 명령어 갯수가 그리 많지 않은 것 같지만 VFP와 NEON 명령어까지 우겨넣으려면 32비트 인코딩으로는 답이 안 나옵니다.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0388e/CHDIBEGC.html
이미 비순차적 실행이 도입된 Cortex-A9만 하더라도 56개의 '물리적 레지스터'를 가지고 있으며, 레지스터 리네이밍으로 활용하고 있습니다.
비순차적 실행시 레지스터 리네이밍을 이용한 성능향상이 어떻게 가능한지는
http://minjang.egloos.com/1241820
이 글 참고하시면 되겠네요.
x86의 경우 32비트에서 8개, 64비트에서 16개의 '논리적 레지스터'만을 가지고 있을 뿐이지만, 내부적으로는 수백개의 '물리적 레지스터'를 가지고 있습니다. 때문에 32비트->64비트 전환에서 '논리적 레지스터'의 갯수가 두배로 증가했지만(8->16이니 16->32때보다 더 효과적이었어야 했을 겁니다) 실질적으로는 별다른 성능 향상이 없었죠.
CISC와 RISC의 차이라는 식의 설명은 맞지 않다는 걸 위에서 이미 이야기했구요.
원본을 못 찾아서 할수없이 엔하위키 링크를 겁니다만 ARM 아키텍쳐별 성능표를 보시면
http://mirror.enha.kr/wiki/ARM(CPU)
'레지스터 부족으로 극도로 제한적인 성능향상'이라는 설명은 잘 맞지 않는 것 처럼 보이는데요?
'논리적 구성상' 레지스터가 부족한 경우가 아닐때에는, 리네이밍과 비순차적실행으로 상당히 커버됩니다만.
그리고, x86->x64 의 경우는, 명령어 체계를 유지하면서 prefix 로 '확장'을 했기때문에, 명령셋의 개선이 크게 있을 수가 없었고, decoder 도 복잡해지는 등으로, '크게' 이득 볼 수는 없었습니다만, 그래도, 나름 이득 봤습니다.
ARMv8 의 경우는 명령셋을 아예 '새로' 구성한거구요. x86 때보다는 유리한 상황인거죠.
그러니까 그건 아키텍쳐의 개선으로 인한 효과지 64비트의 효과가 아니라는 겁니다...
Alquimista님께서 아키텍쳐의 변화를 자꾸 64비트의 효과라고 이야기하시니 저 댓글을 단 거구요.
Alquimista님 //
http://www.arm.com/products/processors/instruction-set-architectures/index.php
A64 is a new "32-bit fixed length instruction set" to support the AArch64 execution state. The following is a summary of the A64 ISA features.
Clean decode table based on 5-bit register specifiers
Instruction semantics broadly the same as in AArch32
31 general purpose 64-bit registers accessible at all times
No modal banking of GP registers - Improved performance and energy
Program counter (PC) and Stack pointer (SP) not general purpose registers
Dedicated zero register available for most instructions
64비트라야만 레지스터 갯수를 늘릴 수 있었다고 이야기하시지만, AArch64도 명령어 길이는 동일하게 32bit입니다. 명령어를 64bit로 늘려버렸다면 캐시성능이나 메모리 요구량에서 상당히 손해를 봤을 겁니다.
(제 얘기도 기본적인 경우는 아키텍처 개선에 따른 것이란 이야기이고, 그 향상이 서정우님께서 언급하신 x86 때의 적은 향상보다는 많을 수 있다는 얘기예요.)
그리고, 제게 쓰신건 아니지만 명령어가 32bit 라거나 등의 얘기는 다른 덧글에 따로 썼었구요.^^
문서 살펴보니 명령어를 추가한게 아니라 완전 갈아 엎었군요.
그런데 OOE(Out of Order Execution)에 대해서는 지나치게 낙관적이신게 아닌가 싶습니다.
수작업 하면서 OOE덕 본 적 한 번도 없었고요, 컴파일 코드 디스어셈블리 봐도 OOE가 발동하는 경우는 극히 드뭅니다. 그만큼 레지스터 갯수가 병목입니다.
OOE는 아주 간혹 컴파일러가 멍청한 코드를 생성 했을 때, 혹은 핸드코딩시 사소한 실수 했을 때 한두 사이클 흘린 것 담아주는 그 이상이 아니라 봅니다.
제대로 된 컴파일러, 그리고 정상적으로 수작업 최적화 된 코드에서는 효율 제로에 수렴합니다.
코드 포함한 내용 추가하였으니 보시고 직접 판단하시기 바랍니다.
과거에 인텔이 펜티엄엠엠엑스를 내놓을때도 "엠엠엑스로 강력해진 멀티미디어"라고 광고했지만 사실 성능향상은 엠엠엑스 인스트럭션보다는 레지스터의 증가때문이였죠.
지금 마케팅적으로 논란이 되는 것은 64비트라는 단어가 전면에 나오기 때문입니다.
"레지스터가 증가하여 성능이 높아졌다"라고 설명하기보다는 "64비트라서 성능이 높아졌다"라고 마케팅되고 있거든요.
"64비트 인스트럭션에 40비트 메모리 어드레싱으로 높은 성능을 낸다!" 라고 주장하는 것처럼 보이니 사람들이 의문을 표하는 것이죠.
"레지스터의 증가로 높은 성능을 낸다!"라고 마케팅한다면 아무도 뭐라할 사람 없을 겁니다.
위에 설명있네요.
64비트 명령어는 제가 아직 직접 체험 못 해봤기에 언급하지 않았을 뿐입니다. 제가 언급하지 않았다고 없는 것은 아니죠.
64비트도 그렇고
음질이나 CPU, 액정 등의 퀄리티를 보면
각 파트별로 진짜 전문가들이 참여한다는 생각이 들더군요.
http://www.clien.net/cs2/bbs/board.php?bo_table=news&wr_id=1687730&sca=&sfl=wr_subject&stx=%EB%B9%A0%EB%A5%B8CLIEN
그거때문에 신앙심이라고 매도되기도 하지만-,-;
수치상으로는 낮은데 써보면 좋다고 말하는건 신앙심이 아니면
설명되지 않는다... 라는거죠ㅎㅎ
본문에 찬양이라불려야할 부분이 어디가 있죠?
왜 다들 애플이 좀더 좋은 기술을 폰에 넣었다라는 말에 이렇게 과민반응을 하는지 모르겠네요,,
애플이라 안되는건가요? 참 안타깝네요
어찌하여간에 내년쯤이면 모바일 시장도 전부 64bit로 넘어가겠군요.
컴 잡지등을 통해 알았던.
문득 시대를 앞서갔던(?) 비운의 CPU 트랜스메타 크루소가. 생각나네요.
(지금도 옆에 그걸 사용한 기종이 3대나 있죠) 크루소가 RISC 였던걸로 기억하는데.
이걸 지금와서 윈도가 아닌 다른 방법으로 활용할 방법은 없겠죠? (램도 작기는 하고....384, 512MB죠..)
from CLiOS
64bit를 말할때 항상 pc를 기준으로 생각들을 하시는거 같은데
여러 블로그에서 지적하듯 pc와 arm은 차이가 있나 봅니다
아키텍쳐 변환으로 매우 큰 성능 향상을 보게 되는건 맞습니다.
결국 64bit 이랑 아키텍쳐의 향상은 따로 떼서 이야기할 수 없는 게 맞나보네요. 그걸 따로 떼서 이야기하려니 논란이 생기는 거군요. *
꼭 64비트로 가야만 했던 게 아닙니다. 다만, 지금 ISA를 갈아엎으면서 여전히 32비트를 고수해야 할 이유가 ARM에겐 없었던 거죠. (어차피 64비트가 필요한 시기가 도래하고 있기도 하구요)
문제는 64bit는 마케팅에 불과 하다라고 주장하시는 분들은 어떠한 설명도 필요없는듯 싶은게 좀 그렇네요
http://yoonjiman.net/2013/09/21/inside-apples-64-bit-ios-7-and-the-prospects-for-a-64-bit-android/ 요 몇일전에 읽었던 블로그인데 여기도 나름 간략하게 설명을 하셔서 참고 삼아 링크 걸어둘께요 여기서도 안드로이드 걱정?을 하고있네요
자칫하면 64bit에 32bit os 달고 나오게 생겼다고,,
System Program 좀 만들어본 입장에선
Dalvik 이 ARM Assembly 로 만들어진것도 아닌데
64bit 으로 변경하는건 그렇게 어려운일은 아닙니다......
x86 64비트 까지 나온 마당에...
ARM 32->64 비트가 가는게 무슨 문제가 될라나요?
안드로이드 64비트 나오느니 못 나오느니 하는 얘기를 애플인사이더에서 하는게 넌센스죠.
혹시 제가 읽어볼만한 블로그 링크라도 가능할까요?
안드진영은 os쪽에 여러가지 걸림돌이 있어서 녹녹치 않을꺼라는 글만 읽어봐서요
그걸 반박하는 글도 좀 읽어보고 싶네요
얼마나 빨리 64비트 ARM 안드로이드가 나올 수 있느냐는 의지의 차이일 뿐입니다.
상대적으로 구글 보다 삼성이 더 절박하긴 할테니 구글에게 조르고 있긴 하겠죠.
가상머신 쓰면 장단점이 있는데, 단점은 가상머신 때문에 성능적으로 손해본다는 점이고.
장점은 플랫폼에 의존적이지 않게 된다는 점입니다.
32->64비트 수준이 아니라 x86의 인텔 CPU에서 돌아가는게 그래서 가능합니다.
NDK 쓰는 일부 개발자외에는 파편화고 뭐고 신경쓸일 거의 없다고 보시면 됩니다.
아키텍쳐 변화에 따른 성능향상도 앱개발자가 아니라 달빅 개발자에게 달려있게 됩니다.
"개발자들 또한 파편화된 안드로이드를 생각해보면 64비트를 적극적으로 지원하지 않을 확률이 크고, 이럴 경우 사용자 입장에서 모든 앱을 64비트로 전환하기 힘들기 때문에 앞서 애플이 겪을 64비트의 전환기에 올 수 있는 단점(메모리 과다 사용)을 꽤 오랫동안 겪을 가능성이 크다."
게다가 메모리는 안드로이드쪽이 훨씬 여유로운거야 이미 아실테고요.
그리고 OS와 컴파일러를 너무 만만하게 보시는 것 같은데 특히 모바일 시장에서 시제품과 제품은 하늘과 땅 차이입니다.
저도 안드로이드의 64비트 전향이 빠르면 좋겠지만 현실적으로 볼 때 빨라야 넥서스 내년도 모델에서나 접할 수 있지 싶습니다.
from CLiOS
단지 이 사실만보면 굳이 64bit 일 필요는 없습니다. 그러므로 이점을 가지고 64bit라서 32개의 레지스터가 가능하다는 것은 이해하기 힘듭니다.
from CLIEN+
시작부터 중간덧글까지 보니 궁금했던건 거의 알게됐어요!
중간부터 끝덧글까진 외계어로 들리기 시작해서 패스
개인소감은 그냥 논리 물리 레지스터고 뭐고 리네이머도 필요없고
몇비트던간에 256개의 (명령어당 1바이트)완전 레지스터를 쓰는
새로운 비호환 아키택쳐가 출현했음 좋겠어요
또한, 레지스터를 늘리다 보니 64bit로의 전환이 필수 불가결하게 되었다.
그리고 이 ARM v8 아키텍쳐를 받아서 재설계 라이센스를 하는 애플이 새계 최초로 ARM v8을 설계하고 판매용 제품을 내놓게 되었다.
이정도가 결론이 될까요?
그나저나 대단하긴 합니다.
세계 최초로 ARM v8 구현 (그것도 커스터마이징 해서)을 하다니...
진짜 아이폰 5s 는 램만 2기가로 나왔어도 정말 까일거리가 없는 폰이 되었을텐데... 그점이 아쉽네요.
세계 최초로 ARMv8을 구현 한건 아닙니다
2. 기존 명령어를 유지하면서 레지스터를 늘리려면 64bit로의 전환이 필요했겠지만 ARM v8은 명령어를 갈아엎었기 때문에 32bit를 유지하면서도 레지스터를 늘릴 수 있었으며(즉 64비트로의 전환은 선택),
3. 애플이 최초로 ARM v8에 기반한 A7 프로세서를 내놓았습니다.
세계 최초 ARMv8을 구현한 곳이 어디에 있나요??
애플을 제외하곤 다른 곳 AP들은 2014년 출시 계획인데요.
제가 모르는 어느 곳에서 출시 되었나요??
두 분 댓글을 보고 헷깔렸던 부분 잘 정리가 되었습니다. 감사합니다.
from CLiOS
아무튼 같은 값이면 ARMv8 기반 64bit CPU를 굳이 안 쓸 이유는 없다...겠죠?
세계 3대 Mobile AP 업체인 애플, 퀄컴, 삼성 중에 애플이 2013년에 64bit을 때려 버렸으니
퀄컴, 삼성이 많이 바쁘겠군요..
(왠지 뜬금없이 미디어텍이 먼저 선수치진 않을까요? -_-a)
ARM쪽에서도 실질적으로 안드로이드 시장을 보고 ARMv8의 모바일 도입을 서둘렀습니다
ARMv8이 실질적으로 나온건 2011년 입니다 당시는 대용량 메모리를 사용하는 서버 시장에 나온
특수한 경우들이였죠
삼성 같은 경우 A15하고 A57하고 엄청난 차이는 안난다고 하니 뭐 샘플 정도는 지금쯤 확보 했을겁니다
잘키운 기술력이나 특허하나가 10년 밥벌이 한다는 게 정말 맞는것 같습니다. PDA시절부터 쌓아온 기술력이라는 것이 정말 무시할 수 없고 지금이야 어느정도 슬슬 한계가 오고 있는 것 같습니다만 64비트의 시도는 올바른 선택이라 생각이 드네요.
아..나 89학번이지. ;;;
정리를 하자면 "64비트"는 순수하게 정수 연산이 한 사이클에 64비트가 된다, 고로 포인터가 64비트가 된다 이것이 핵심입니다. 그런데 지금 주장하시는 대부분은 64비트가 아닌 레지스터 개수가 늘어남에 따른 주장인데 이건 솔직히 64비트라서 그런 것이 아니라 64비트로 가면서 아키텍처 자체를 바꿀 수 있는 기회가 있어서입니다. 많은 초보자분들에게 혼동을 줄 것 같아 안타깝습니다. 최소한 현대 아키텍처에서 물리 레지스터와 논리 레지스터 (혹은 architectural register)가 따로 있다는 것만 아셔도 좋았을 것 같습니다.
추가: 저는 참고로 64비트 도입을 굉장히 반기는 사람입니다. 다만 기술적인 사실을 확실히 하자는 의미 댓글 남겼습니다.
예제 포함한 내용 추가하였으니 이견 있으시면 다른 예제를 제시하시거나 구체적으로 찍어서 주시기 바랍니다.
논리 레지스터는... 뭐 더 드릴 말씀이 없네요. 레지스터는 그냥 하드웨어입니다.
yute님 말대로 32b에서 conditional exe bit를 register index확장에 썼더군요. (conditional exe은 대대로 deep-pipeline이나 superscalar여렵게 만드는 요인이였죠.)
http://nominolo.blogspot.com/2012/07/arms-new-64-bit-instruction-set.html
즉 32비트때도 명령어만 바꾸면 레지스터 늘리는건 가능했습니다.
원래 cpu 처리비트가 늘어나면 성능 향상 효과가 있었습니다. 과거엔 분명 효과가 있었죠. 하나의 레지스터에서 처리하는 데이터가 늘어나고 메모리에서 읽어오는 데이터의 양이 늘어납니다.
단순히 for 루프를 돌리는 이터레이터로 사용하면 과거 8비트에서는 최소한 레지스터 2개를 연결하여 사용했고, 16비트에서도 하나의 레지스터를 사용하는 것은 65535루프 이하에서나 가능하고 많은 경우 레지스터 2개를 연결하여 사용했죠. 그러나 32비트에서는 32비트를 다 채우는 루프는 거의 없죠. 대부분의 정수연산은 32비트에서 끝납니다. 그러므로 레지스터가 커져 속도를 올리는 효과는 과거에 비하여 떨어지게 되죠.
메모리에서 읽어오는 데이터는 현재의 cpu는 전혀 상관 없게 됩니다. 메모리 캐쉬가 중간에 콘트롤 하고 있고 메모리 버스는 cpu 비트수와 상관 없이 동작하는 것이 대부분입니다.
이런 상황이니 단순히 64비트의 이점은 메모리 엑세스 범위가 넓어졌다는 것 밖에는 크게 부각되는 부분이 없는 것이죠. 그래서 많은 사람들이 64비트가 별로 유리하지 않다고 하는 것이죠.(메모리가 적은 상태에서는요)
팁과 강좌에다 왜 ARM에서도 64비트가 무의미 한지
메모리이득 외에는 없는지 강좌를 남겨 주신다면 좋겠습니다.
그냥 억지로 반박하려는 것으로 밖에 보이지를 않네요.
오히려 그에 대한 답변들이 Alquimista님으로부터 하나도 없네요.
그리고 무의미하단 분은 없는 것 같습니다. 대부분 말씀하시는 건 64비트 전환에서의 효과보다 아키텍처의 변화가 성능개선에 지배적인 영향을 준다는 말과 아키텍처 변화랑 64비트 전환이랑 별도로 가능하다(따라서 아키텍처 변화로 성능 개선이 된게 곧 64비트라서 개선이 됐다는 말은 틀리다)는 말인 것 같은데요.
댓글에 글 하나 새로 쓰는 것 만큼 자세하게 남겨주신 분들도 많은데, 제대로 읽어보신 것은 맞으시죠?