성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 왜 구조체는 16 바이트의 크기가 적합한가?</h1> <p> 지난 글에서,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C# - 구조체의 크기가 16바이트가 넘어가면 힙에 할당된다? ; <a target='tab' href='https://www.sysnet.pe.kr/2/0/12619'>https://www.sysnet.pe.kr/2/0/12619</a> </pre> <br /> "16바이트"는 그래도 의미가 있는 숫자입니다. 관련해서 마이크로소프트의 문서를 보면,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Choosing Between Class and Struct ; <a target='tab' href='https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct'>https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct</a> </pre> <br /> 다음의 조건을 만족하지 않는 한 class를 사용하는 것을 권장합니다.<br /> <br /> <ul> <li>논리적으로 단일 값을 표현하는 경우</li> <li>16바이트 이하의 크기를 가진 경우</li> <li>불변 타입으로 대우하려는 경우</li> <li>박싱 연산이 자주 발생하지 않는 경우</li> </ul> <br /> 이 중에서 유독 정확히 16바이트라는 수치를 명시한 이유가 궁금하지 않을 수 없습니다. 얼핏 생각해 보면, <a target='tab' href='https://ko.wikipedia.org/wiki/%EC%9B%8C%EB%93%9C_(%EC%BB%B4%ED%93%A8%ED%8C%85)'>CPU의 워드 단위</a>로 32비트에서는 4바이트, 64비트에서는 8바이트만큼 하나의 연산으로 취급할 수 있기 때문에 속도 면에서 보면 16바이트라고 해서 딱히 빨라질 이유가 없는 것입니다.<br /> <br /> 이에 대한 비밀은, <a target='tab' href='https://www.sysnet.pe.kr/2/0/11423'>SSE(Streaming SIMD Extensions)</a> 레지스터와 연관이 있습니다.<br /> <br /> x86 인텔 CPU의 경우 128비트 크기의 SSE 레지스터를 xmm0 ~ xmm7까지, 64비트인 경우 추가로 xmm8 ~ xmm15를 가지고 있는데, 바로 이 레지스터를 사용하기 때문에 128비트, 즉 16 바이트 크기에 대해서는 레지스터 하나로 처리할 수 있어 구조체의 권장 크기가 된 것입니다.<br /> <br /> 과연 그런지 눈으로 확인해 볼까요? ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public <span style='color: blue; font-weight: bold'>struct Size16</span> { public long l1; public long l2; } class Program { static void Main(string[] args) { Size16 v1 = new Size16(); <span style='color: blue; font-weight: bold'>Size16 v2 = v1;</span> } } </pre> <br /> 위와 같이 코딩을 하고, 디버깅을 진행해 "<a target='tab' href='https://www.sysnet.pe.kr/2/0/1022'>.NET Disassembly</a>" 창을 띄워 기계어 코드로 확인해 보면 다음의 xmm0 레지스터 사용을 확인할 수 있습니다. (그런데, 사실 CPU/메모리 간의 64비트 I/O 입출력은 마찬가지일 텐데 CPU 내부에서의 16바이트 접근만으로 얼만큼의 성능 효과가 있는지는 의문입니다.)<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 18: Size16 v2 = v1; 00007FFA300608D1 C4 E1 7A 6F 45 38 <span style='color: blue; font-weight: bold'>vmovdqu xmm0</span>,xmmword ptr [rbp+38h] 00007FFA300608D7 C4 E1 7A 7F 45 28 <span style='color: blue; font-weight: bold'>vmovdqu</span> xmmword ptr [rbp+28h],<span style='color: blue; font-weight: bold'>xmm0</span> </pre> <br /> 그러니까, 적어도 16바이트까지는 (v)mov(dqu) 명령어로 빠르게 데이터를 옮길 수 있기 때문에 구조체의 권장 크기가 된 것입니다. (dqu == <a target='tab' href='https://www.codingame.com/playgrounds/283/sse-avx-vectorization/what-is-sse-and-avx'>double-quadword-unaligned</a>, <a target='tab' href='https://learn.microsoft.com/en-us/cpp/cpp/m128i'>__m128i</a>)<br /> <br /> <hr style='width: 50%' /><br /> <br /> 재미 삼아서, 자신의 컴퓨터에 있는 CPU가 어느 정도의 SSE/AVX를 지원하고 있는지 알고 싶다면 간단하게 coreinfo 도구를 활용할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > Coreinfo v3.52 ; <a target='tab' href='https://learn.microsoft.com/en-us/sysinternals/downloads/coreinfo'>https://learn.microsoft.com/en-us/sysinternals/downloads/coreinfo</a> </pre> <br /> i5-4670 CPU에서 이를 실행시켜 보면 다음의 결과를 확인할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > C:\Windows\System32> <span style='color: blue; font-weight: bold'>coreinfo</span> Coreinfo v3.52 - Dump information on system CPU and memory topology Copyright (C) 2008-2021 Mark Russinovich Sysinternals - www.sysinternals.com Intel(R) Core(TM) i5-4670 CPU @ 3.40GHz Intel64 Family 6 Model 60 Stepping 3, GenuineIntel Microcode signature: 00000028 HTT * Hyperthreading enabled <a target='tab' href='https://devblogs.microsoft.com/oldnewthing/20241015-00/?p=110374'>CET - Supports Control Flow Enforcement Technology</a> ...[생략]... FPU * Implements i387 floating point instructions MMX * Supports MMX instruction set MMXEXT - Implements AMD MMX extensions 3DNOW - Supports 3DNow! instructions 3DNOWEXT - Supports 3DNow! extension instructions <span style='color: blue; font-weight: bold'>SSE * Supports Streaming SIMD Extensions SSE2 * Supports Streaming SIMD Extensions 2 SSE3 * Supports Streaming SIMD Extensions 3 SSSE3 * Supports Supplemental SIMD Extensions 3</span> SSE4a - Supports Streaming SIMDR Extensions 4a <span style='color: blue; font-weight: bold'>SSE4.1 * Supports Streaming SIMD Extensions 4.1 SSE4.2 * Supports Streaming SIMD Extensions 4.2</span> <span style='color: blue; font-weight: bold'>AES * Supports AES extensions AVX * Supports AVX instruction extensions AVX2 * Supports AVX2 instruction extensions</span> AVX-512-F - Supports AVX-512 Foundation instructions AVX-512-DQ - Supports AVX-512 double and quadword instructions AVX-512-IFAMA - Supports AVX-512 integer Fused multiply-add instructions AVX-512-PF - Supports AVX-512 prefetch instructions AVX-512-ER - Supports AVX-512 exponential and reciprocal instructions AVX-512-CD - Supports AVX-512 conflict detection instructions AVX-512-BW - Supports AVX-512 byte and word instructions AVX-512-VL - Supports AVX-512 vector length instructions ...[생략]... </pre> <br /> "AMD Ryzen 7 PRO 4750G"에서도 위와 유사한 결과를 얻을 수 있는데요, 그러니까 근래의 컴퓨터들은 대부분 256비트의 레지스터(YMM0~YMM15)들이 있으므로 이것을 활용하면 구조체의 데이터 이동을 32바이트까지 빠르게 옮길 수 있지만 아쉽게도 .NET JIT 컴파일러는 아직 구조체 연산에 AVX 레지스터를 활용하진 않고 있습니다.<br /> <br /> 다행히 JIT 컴파일러에 SSE/AVX 관련 통합이 되고 있다는 소식은 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > The JIT finally proposed. JIT and SIMD are getting married. ; <a target='tab' href='https://devblogs.microsoft.com/dotnet/the-jit-finally-proposed-jit-and-simd-are-getting-married/'>https://devblogs.microsoft.com/dotnet/the-jit-finally-proposed-jit-and-simd-are-getting-married/</a> Using .NET Hardware Intrinsics API to accelerate machine learning scenarios ; <a target='tab' href='https://devblogs.microsoft.com/dotnet/using-net-hardware-intrinsics-api-to-accelerate-machine-learning-scenarios/'>https://devblogs.microsoft.com/dotnet/using-net-hardware-intrinsics-api-to-accelerate-machine-learning-scenarios/</a> </pre> <br /> 위의 두 번째 링크가 최신 소식인데 .NET Core 3.0부터 AVX 명령어를 사용한다는데요,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > On .NET Core 3.0, the system will use the new managed implementation with AVX hardware intrinsics. </pre> <br /> 하지만 엄밀히 이것은 구조체 연산에 사용한다는 것이 아니고 ML.NET이나 수치 연산을 위한 라이브러리에 한정된 것으로 보입니다. 아무튼 언제까지 16바이트 권장이 유지될지는 모를 일입니다. ^^ (어쩌면 이것도 하위 호환이라는... ^^;)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
6018
(왼쪽의 숫자를 입력해야 합니다.)