<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>engineer_diary</title>
    <link>https://engineer-diary.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 21:01:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>wu2ee</managingEditor>
    <item>
      <title>POCU COMP3200 C++ 언매니지드 프로그래밍 후기</title>
      <link>https://engineer-diary.tistory.com/398</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;수강 목적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 프로그래밍 수업을 들으면서 저수준에서 메모리를 관리하고 어셈블리어까지 컴퓨터 공학적인 지식을 배우는 것이 즐거웠다. C++ 도 언매니지드 프로그래밍 답게 메모리 관리 측면에서 개체지향까지 곁들여서 어떤식으로 처리할 수 있는지 궁금했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++ 은 사실 학교에서도 OpenCV 로 이미지 처리를 하고, 인턴을 통해 SVM Top View 를 개발할 때도 썼었지만, 거의 로직 위주의 개발이 많았고, C++ 과 언매니지드 프로그래밍 관점에서는 놓치는 부분이 많았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 로직에 집중하는 것도 좋지만, 저수준에서 메모리 관리를 직접 해보고 동작하는 것을 보는 것이 가려운 부분을 긁어주는 부분이 컸기 때문에, 이번 강의는 재밌을 것 같았고, 개체지향 관점에서의 메모리 관리도 알아볼 수 있겠다고 생각하여 수강하게 되었다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;강의 내용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++ 은 사실 문법자체가 익숙하지 않았다. 하지만 앞선 과정에서 기초를 다져왔기 때문에 빠르게 그 언어에 대한 특징을 습득할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 C 언어와 같이 포인터도 다루지만, 참조라는 것을 추가적으로 배울 수 있었고, C++ 관점에서의 개체지향 프로그래밍을 배울 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 개발자이기 때문에 단순히 생성자를 사용하는 정도로만 실무에서 사용해왔었는데, C++ 에서 생성자와 초기화리스트, 복사 생성자, 생성자 오버로딩, 소멸자 등을 배우면서 개체의 라이프 사이클에 대해서 자세하게 배울 수 있었고 지금껏 써왔던 자바와도 비교가 되면서 더욱 흥미로웠고 재밌었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 연산자 오버로딩은 매우 새로웠는데, C++ 에서 막연하게만 쓰던 연산자들이 사실은 오버로딩을 통해서 기능을 사용할 수 있었다는 점이 흥미로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어셈블리어 관점에서 코드를 까볼 수도 있었고 가상 함수, 가상 테이블을 통해 다형성이 어떻게 동작하는지 자바와 어떻게 다른지 비교를 통해 학습할 수 있어서 더 잘 이해할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 기존에 C++ 을 통한 STL 을 사용한 코딩 테스트 문제를 풀곤 했었는데, 중간고사까지 배워온 빌드업을 이어서 템플릿 프로그래밍을 이해하면서 vector 가 무엇이고 map 이 무엇인지 어떻게 이 자료구조들이 구현될 수 있었는지 이해할 수 있었다. 예전에는 그냥 가져다 사용하기만 했었는데, 이러한 배경들을 이해하고나니 더욱더 개념들이 잘 체화될 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 템플릿 프로그래밍 기반으로 '스마트 포인터' 개념을 익히면서 자동으로 메모리관리가 되는것이 얼마나 편한지 체감할 수 있었다. 이외에도 rvalue, 이동생성자 개념을 통해 불필요한 복사를 막고, 람다 표현식을 통한 처리 등등 정말 많은 걸 배웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;강의 내용을 되돌아보면 C++ 과목은 가장 많은 내용을 학습했던 것 같은데, 하나하나가 너무 재밌었다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;강의 실습 &amp;amp; 과제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 C++ 프로그래밍 실습, 과제는 크게 어려움을 느끼진 않았던 것 같다. 과제2에서 개체의 메모리 관리하는 부분에 살짝 애를 먹긴 했지만, 다른 과목에 비해서는 즐겁게 실습, 과제에 임했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 모던 C++ 을 이용하여 과제, 실습을 진행하면서 스마트 포인터가 어떻게 활용되는지 알 수 있어서 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;중간 &amp;amp; 기말 시험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 유형은 다른 과목과 비슷했다. 개인적으로 C++ 은 되게 즐겁게 공부했어서 시험이 크게 어렵다고 느껴지지는 않았다. 다만 참조, rvalue 를 어느 상황에서 쓰는지 확실히 체화가 되지는 않았는지, 시험때 조금 헷갈리는 부분이 있었던 것 같다. 확실히 IDE 에 의존적으로 개발을 해오다보니 단순히 코드만 보고 문제가 있는지 판단하는 것이 쉽지는 않았던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;점수는..?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;649&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnICQ0/btsLsMCR6ZG/Sj0uaUEQq5zFjI8lR31ekk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnICQ0/btsLsMCR6ZG/Sj0uaUEQq5zFjI8lR31ekk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnICQ0/btsLsMCR6ZG/Sj0uaUEQq5zFjI8lR31ekk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnICQ0%2FbtsLsMCR6ZG%2FSj0uaUEQq5zFjI8lR31ekk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;926&quot; height=&quot;649&quot; data-origin-width=&quot;926&quot; data-origin-height=&quot;649&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;실습, 과제는 모두 만점을 받았고, 중간, 기말고사도 모두 80점 이상 받았다. C++ 수업을 들으면서 개인적으로 C++ 을 이용한 사이드 프로젝트를 하고 싶을 정도로 학기내내 재밌었다..&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 1.62em; letter-spacing: -1px;&quot;&gt;느낀점&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;C++ 언매니지드 프로그래밍 수업을 들으면서 C 에서 익숙해진 포인터가 장착된 채 여러 내용들을 배워나갔는데, 그냥 재밌었다. 계속 재밌었다는 말을 반복하는 것 같은데, 아무래도 나는 언매니지드 프로그래밍을 하면서 재미를 많이 느끼는 것 같다. (자동으로 누군가가 해주는 것보다 내가 하나씩 다 제어하는 것이 매력적이었다.)&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;C++ 개념이 이제 어느정도 정립되었다는 생각이 들었고, 알고리듬적으로 C++ 기반 예제 코드들이 많이 있는데, 이제 더이상 겁내지 않고 잘 읽어낼 수 있다는 자신감이 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 POCU 수업의 5/(7 to 12) 을 들었다. 이제 앞으로 강의 2개가 남았다. 알고리듬과 어셈블리어.. 어셈블리어도 너무 재밌을 것 같지만, 우선순위를 고려했을때, 알고리듬을 통해 많은 점을 얻을 수 있을 것 같아 다음학기에는 알고리듬을 수강할 것 같다. 언제나 컴퓨터 공학의 기초를 쌓는 것은 즐거운 것 같다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>POCU</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/398</guid>
      <comments>https://engineer-diary.tistory.com/398#entry398comment</comments>
      <pubDate>Mon, 23 Dec 2024 23:47:59 +0900</pubDate>
    </item>
    <item>
      <title>POCU COMP2500 개체지향 프로그래밍 및 설계 (Java) 후기</title>
      <link>https://engineer-diary.tistory.com/397</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;수강 목적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 개체지향 프로그래밍 및 설계 강의를 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인은 이미 백엔드 개발자이기 때문에 자바에는 익숙한 상태였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 비전공자로서 늘 기초 지식에 대해서 깊게 배우는 것에 대한 갈망이 남아있고, POCU 의 모든 과정을 듣기로 결심했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개체지향을 어느정도는 알고 있었지만, 관련 실습, 과제들이 어떻게 나오는지 궁금하기도 했고, 포프 선생님이 생각하는 개체지향에 대한 내용을 알고 싶었다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;강의 내용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 개체지향 강의는 다른 과목들과 달리 추상적인 내용이 많았다. OOP 의 필요성부터 OOP의 4대 특성까지 예시를 들어가며 설명해주셔서 더 잘 이해할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 개체지향 '설계' 를 위해 상속을 이해하기 위한 방법, 개체 모델링등을 실 생활 예제를 통해 설명해주셔서 어느 상황에 적절하게 상속을 써야하는지 알 수 있었다. 설계에 정답은 없지만, 포프님이 하나씩 설계해나가는 모습을 보면서 어떤식의 사고를 해야하는지 알 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 항상 상속과 컴포지션을 어느 상황에서 사용하는 것이 옳은지 헷갈리곤했는데, 각각이 어떤 케이스에 유리한지 경우를 자세하게 소개해주셔서 더욱 개념을 잘 적립하고, 어떻게 써먹어야할지 감을 잡을 수 있었다. 특히, has-a, is-a 관계에 대해서 명확하게 이해할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간고사 이후에는 개체지향 설계에서 꽃이라고 볼 수 있는 다형성에 대해서 학습했는데, 이때 늦은 바인딩, 이른 바인딩에 대한 키워드를 이해할 수 있었고 인터페이스를 통해 다형성을 어떤식으로 구현하는지 이해할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도 결합도가 강하다, 느리다의 개념과 디자인 패턴, SOLID 설계 정신을 학습하면서 각각의 상황이 의미하는바와 적절한 설계를 어느 상황에 적용하는 것이 좋은지 학습할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;강의 실습 &amp;amp; 과제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개체지향 프로그래밍 설계의 실습 과제는 앞선 과목과 다르게 '설계'의 관점에서 채점을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적절한 개체의 캡슐화, 상속관계를 지키지 않으면 감점을 받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습, 과제의 명세를 명확하게 이해하지 않고, 오직 구현을 위한 프로그래밍을 한다면 점수를 온전히 획득할 수 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 모든 과제는 유저 스토리 기반으로 어떤 개체를 만들고 개체간의 관계를 상속으로 할지, 메서드는 어느 개체에게 책임을 지울지 많은 고민을 할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 과제3은 명세도 엄청 복잡하고 개체간의 책임 및 구현을 명확하게 설계하지 않으면 절대로 통과할 수 없었다. 과제3을 통해서 개체 지향 설계의 쓴맛을 제대로 맛볼 수 있었다.. 그러나 그만큼 설계에 대해서 많은 고민을하고 내가 이해한 명세와 수업시간에 배운 내용을 토대로 설계하고자 노력하면서 한층 더 성장할 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;중간 &amp;amp; 기말 시험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 과목과 시험의 유형은 비슷한 부분도 있었지만 '설계' 과목답게 특정 상황에 대한 설계를 하는 문제도 있었다. 최대한 실습,과제를 기반으로 시험에 녹여내려고 했다. 약간 아쉬운점은 다른 과목과 달리 '설계' 의 관점이다보니 감점이 된 포인트에서 어느 부분이 문제인지 알고 싶었는데, 이를 알지 못해서 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;점수는..?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;923&quot; data-origin-height=&quot;645&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QOlSF/btsLsqUlf7R/kPZ0m0ORtA0pX6ECTtd9xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QOlSF/btsLsqUlf7R/kPZ0m0ORtA0pX6ECTtd9xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QOlSF/btsLsqUlf7R/kPZ0m0ORtA0pX6ECTtd9xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQOlSF%2FbtsLsqUlf7R%2FkPZ0m0ORtA0pX6ECTtd9xK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;766&quot; height=&quot;535&quot; data-origin-width=&quot;923&quot; data-origin-height=&quot;645&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;자바 수업도 재수강을 했다.. 아깝게 84%로 떨어졌다.. 지난 학기에 들었지만, 현업과 같이하면서 기말고사 준비를 많이 준비하지 못했다 ㅠㅠ&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 다시 들으면서 좀더 개체지향 설계에서 간과했던 포인트들을 다시 정리하면서 중간, 기말고사도 더 잘 볼 수 있엇다. 하지만 설계의 포인트에서 어느 부분이 문제인지 피드백을 받지 못한 점은 아직 아쉽다..&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 1.62em; letter-spacing: -1px;&quot;&gt;느낀점&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;개체지향 프로그래밍 수업을 들으면서 개체를 어떤 기준으로 분리하면 좋을지 머릿속에 적립이 되었다. 실생활의 어떤 상황을 개체로 모델링하고, 적절하게 개체의 멤버 변수를 설계하고 상속을 어느 시점에하면 좋을지, 이럴때는 컴포지션이 더 좋고 등등 이런 내용들이 익숙해질 수 있었다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;이제는 컴퓨터의 동작원리를 넘어서서 개체지향 설계 관점에서 더나은 시스템을 만들어나갈 수 있겠다는 자신감도 얻을 수 있었다. 실습과 과제도 그렇고 이론까지 상당히 추상적인 부분이 많아서 각 모델링 방법의 장단점들이 상당히 많고 소수설, 다수설 등 정답이 존재하지 않는 부분이 많았다. 이러한 부분들은 두고두고 필요할 때마다 다시한번씩 수업때 배웠던 내용을 다시 한번 보면서 내 것으로 체화해야 겠다는 생각을 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 POCU 수업의 4/(7 to 12) 을 들었다. 개체지향 설계 과목과 함께 C++ 언매니지드 프로그래밍도 같이 들으면서 과정을 소화했는데, 확실히 시험 기간에 엄청난 부담이 되었다. 다음에는 재수강을 절 때 하지 않겠다는 생각으로 이번 학기는 둘다 열심히 했던 것 같다.. 개체지향 설계는 앞으로 실무에서도 많이 쓸 것이기 때문에 이번 강의를 계기로 기반을 다지고 더 나은 설계를 하는데 자신감을 가지고 소통할 수 있겠다는 생각이 들었다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>POCU</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/397</guid>
      <comments>https://engineer-diary.tistory.com/397#entry397comment</comments>
      <pubDate>Mon, 23 Dec 2024 23:17:45 +0900</pubDate>
    </item>
    <item>
      <title>POCU COMP2200 C 언매니지드 프로그래밍 후기</title>
      <link>https://engineer-diary.tistory.com/396</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;수강 목적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POCU 아카데미의 로드맵을 쭉 따라가서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&quot;전문 프로그래머가 되기 위한&quot;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;과정을 밟아가고 싶었다. 현재 총 7개의 로드맵이 열려있는데, 이제 3개의 로드맵이 끝났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 프로그래밍 수업은 사실 대학교때도 수업을 들었다. 하지만 C언어로부터 컴퓨터 공학 지식을 배운다기보다는 단순히 그 언어를 배우는데 초점을 두고 배웠기 때문에 당시에 공부를 할 때도 깊은 이해를 할 수 없었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과목 이름에서도 &quot;언매니지드&quot; 가 붙어있듯이 &quot;관리되지 않는&quot; 이라는 말을 몸소 경험해보고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 개발자로 살아가고는 있지만, 기초를 잘 아는 것이 항상 중요하다고 생각했고 이러한 욕망은 COMP2200 수업으로 채우기에 충분했던 것 같다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;강의 내용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POCU 강의를 여러번 들어본 결과, 항상 초반에는 해당 강의에서 사용하는 언어의 특징을 한 주차 정도 설명해주신다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C언어도 마찬가지로 진행되었다. 그런데, C언어는 단순히 기본 자료형을 익히는 것을 넘어서서 하드웨어를 이해해야 했다. 이러한 히스토리들을 자세히 설명해고 있기 때문에 단순히 기본 자료형에서 한번 더 생각하는 시간을 가질 수 있었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 프로그램 빌드 과정, 스택 메모리, 포인터 등을 학습하면서 스택 메모리를 어셈블리어까지 뜯어가며 공부한 내용이 가장 인상 깊었고, 머릿속에 깊게 박혔다. 내용이 어려웠던 만큼 이를 이해하기 위해 고민하고 검색도 하며 부족한 부분을 채워나갔고, 이러한 시간들이 쌓여서 이제는 함수가 호출될 때 메모리에서 어떤식으로 메모리가 동작이 될 것인지 조금이나마 상상이 되는 것 같아 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 기반으로 C 언어 문자열, 콘솔 입출력 들을 계속해서 &quot;메모리&quot; 관점에서 생각하며 학습을 하는 것이 추후에 구조체, 함수 포인터, 구조체, 가변인자 함수 등등 을 학습하는데 많은 도움이 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 앞서 배운 포인터를 기반으로 동적 메모리 할당, 다중 포인터 등을 배우고, 이를 기반으로 간단한 자료구조 및 구현까지 배움으로서 포인터를 아주 통달할 수준까지 머릿속에 집어 넣었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 언급한 내용은 모두 C89 기반으로 강의 내용이 진행되었다면, 강의 후반부에는 C99 기반으로 어떠한 점이 개선되었는지 쉽게 알려주어서 어떤식으로 C언어가 발전해 나가고 있는지까지 이해할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;강의 실습 &amp;amp; 과제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 언매니지드 프로그래밍 수업의 실습 과제는 앞서 들었던 기초, 수학 과목과 차원이 다를 정도로 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 C언어의 특징을 이용하여 실습과 과제를 구현해야 했고, 실습과 과제 하나하나 모두 쉽지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, 자료구조를 구현해야 하는 실습8과 다중 포인터를 사용하는 과제3을 진행하면서 정말 많은 것을 배울 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 과제 3의 경우 4중 포인터까지 써야했고, 동적 할당된 메모리를 일일이 다 내가 메모리를 열어준 놈은 내가 알아서 다 닫아주는 작업을 진행했다. 이 과정에서 정말로 프로그래머로서 C언어를 사용한다면 메모리 할당을 해주는 만큼 메모리 해제를 놓치지 않고 실수 없이 잘 해내는 것이 정말로 중요하겠구나 많이 생각했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;중간 &amp;amp; 기말 시험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 해당 과목에서는 IDE 를 사용하지 말고 메모장에서 프로그래밍을 하는 것을 권장했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 머릿속에서 내 코드를 보며 뇌버깅을 할 수 밖에 없었고, 이러한 연습을 통해서 코드만 보고도 런타임 오류인지, 컴파일 오류인지를 판단해보는 연습을 많이 했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 시험에서도 위와 같은 내용을 집요하게 물어보고, 이러한 훈련들이 시험을 보는데 도움이 됐던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;점수는..?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/55j6f/btsJgc9FhNz/TAVBHQadFwB1uaISCnPxS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/55j6f/btsJgc9FhNz/TAVBHQadFwB1uaISCnPxS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/55j6f/btsJgc9FhNz/TAVBHQadFwB1uaISCnPxS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F55j6f%2FbtsJgc9FhNz%2FTAVBHQadFwB1uaISCnPxS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1025&quot; height=&quot;472&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;사실 C언어 수업은 재수강을 했다. 지난 학기에 들었지만, 기말고사를 공부를 할 수 있는 시간을 도저히 낼 수 없어서 포기를 했었다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;지난 학기에서는 기말고사를 보지 않았고, 실습 8과 과제 3을 만점받지 못했다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;재수강을 하면서 놓쳤던 실습과 과제를 모두 다시 도전하면서 놓친 포인트를 이해하고 만점을 받을 수 있었다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;중간고사때는 문자열과 관련된 내용들이 많이 등장하는데 이 부분에서 지난 학기 중간고사의 경험이 있음에도 문자열부분에 대한 디테일한 부분까지 챙기지 못해서 점수가 썩 좋지는 못했던 것 같다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;기말고사는 그래도 악착같이 동적할당부터 놓치는 부분 없이 꼼꼼히 공부해서 점수를 만회할 수 있어 좋았다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-size: 1.62em; letter-spacing: -1px;&quot;&gt;느낀점&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 언매니지드 프로그래밍 수업을 들으면서 컴퓨터 동작 원리 중, 메모리가 어떻게 동작하는지 머릿속에 적립이 되었다. 또한 프로그래밍의 동작 원리까지 이해를 하면서 기본적으로 언매니지드, 컴파일 언어에 대한 원리를 깨우치는 시간을 가질 수 있었다. 그리고 포인터가 더이상 두렵지 않았고 오히려 이를 통해서 메모리를 관리하는 프로그래머가 작성하는 코드들이 정말로 컴퓨터의 low 영역을 건드릴 수 있다는 사실을 깨우칠 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 동작만하는 코드를 다루는 것이 아니라 더 깊게 사고하고 어떠한 문제가 있을지 사고하는 능력을 배웠고 이러한 지식들은 저수준 언어를 사용하든 고수준 언어를 사용하든 항상 어떠한 영향을 끼칠지 사고하면서 코드를 작성할 수 있는 능력을 배웠다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이제 POCU 수업의 3/(7 to 12) 을 들었다. 사실 이번학기 개체지향 설계 과목도 들었는데, 두 과목을 같이 하는 것과 회사 생활까지 같이하는게 상당한 무리가 있는 것 같다... 개체지향 설계 과목은 재수강을 할 것 같고, 그 다음 과목인 C++ 언매니지드 프로그래밍과 같이 진행할 예정이다. 힘들지만 그래도 배움이 너무 즐겁다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>POCU</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/396</guid>
      <comments>https://engineer-diary.tistory.com/396#entry396comment</comments>
      <pubDate>Mon, 26 Aug 2024 00:20:37 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 35일차 봉화희제후와 메모리 장벽(2)</title>
      <link>https://engineer-diary.tistory.com/395</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;/p&gt;</description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/395</guid>
      <comments>https://engineer-diary.tistory.com/395#entry395comment</comments>
      <pubDate>Wed, 29 May 2024 08:33:05 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 34일차 봉화희제후와 메모리 장벽(1)</title>
      <link>https://engineer-diary.tistory.com/394</link>
      <description></description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/394</guid>
      <comments>https://engineer-diary.tistory.com/394#entry394comment</comments>
      <pubDate>Tue, 28 May 2024 07:21:48 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 33일차 다중 스레드 성능 방해자</title>
      <link>https://engineer-diary.tistory.com/393</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU가 4바이트 정수에 접근할 때, 캐시 히트를 하지 못하면 간단히 캐시에 4바이트 정수를 저장하면 된다고 생각함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그러나 그렇지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐시와 메모리 상호 작용의 기본 단위: 캐시 라인&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;프로그램이 어떤 데이터에 접근하면 다음에는 인접한 데이터에 접근할 가능성이 높으므로 접근해야 할 데이터만 캐시에 저장하지 않음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 데이터가 있는 곳의 &amp;lsquo;묶음&amp;rsquo; 데이터를 캐시에 저장함.&lt;/li&gt;
&lt;li&gt;이를 캐시 라인 이라고 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;묶음 데이터는 일반적으로 64바이트임.&lt;/li&gt;
&lt;li&gt;캐시와 메모리 사이의 상호 작용에 대한 세부 내용은 다중 스레드 프로그래밍이고, 일반인이라면 생각해 낼 수 없음. &amp;rarr; 매우 흥미로운 문제를 가져옴.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;첫 번째 성능 방행자: 캐시 튕김 문제&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;atomic&amp;lt;int&amp;gt; a;

void threadf()
{
	for (int i = 0; i &amp;lt; 500000000; i++)
	{
		++a;
	}
}

void run()
{
	thread t1 = thread(threadf);
	thread t2 = thread(threadf);
	
	t1.join();
	t2.join();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;atomic&amp;lt;int&amp;gt; a;

void run()
{
	for (int i = 0; i &amp;lt; 1000000000; i++)
	{
		++a;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 프로그램은 스레드 2개를 이용해 전역변수 a를 1씩 5억번 증가시킴.&lt;/li&gt;
&lt;li&gt;아래 프로그램은 단일 스레드로 전역변수 a를 1씩 10억번 증가시킴&lt;/li&gt;
&lt;li&gt;다중 코어 컴퓨터 기준, 첫 번째 프로그램 실행 시간은 16초, 두번 째 프로그램 실행 시간은 8초였음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왜 스레드 2개쓴 프로그램이 오히려 더 느릴까?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;리눅스 perf 도구를 이용하여 두 프로그램을 분석하면 &amp;lsquo;insn per cycle&amp;rsquo; 항목을 보자.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 항목은 하나의 클럭 주기에 CPU가 실행하는 프로그램에서 기계 명령어를 몇 개 실행하는지 알려줌.&lt;/li&gt;
&lt;li&gt;다중 스레드 프로그램은 insn per cycle 이 0.15로, 하나의 클럭 주기 동안 기계 명령어가 0.15개 실행 되었음.&lt;/li&gt;
&lt;li&gt;단일 스레드 프로그램은 0.6으로 다중 스레드 프로그램의 네배에 달함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;참고로, a 변수를 원자적 변수가 아닌 int 형으로 정의하면 실행 시간은 더욱 빨라짐.&lt;/li&gt;
&lt;li&gt;이렇게 다중 스레드 프로그램의 성능이 좋지 않은 이유가 무엇일까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 일관성을 보장하기 위해, 두 코어의 캐시에 전역 변수 a 처럼 저장 되어야 함.&lt;/li&gt;
&lt;li&gt;ex) 캐시 1에서 a 변수를 1로 업데이트 하면 캐시 2의 a 변수를 무효화(invalidation) 해야 함. &amp;rarr; 여기서 첫 번째 캐시 튕김이 발생함.&lt;/li&gt;
&lt;li&gt;캐시 2는 캐시 무효화가 되었기에 어쩔 수 없이 메모리에서 직접 a 변수 값을 읽어야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;근데 이때 또, a 변수 값을 1을 더해야 하므로 캐시 일관성을 보장하기 위해 이번에는 캐시 1의 a 변수를 무효화 해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이렇게 서로 끊임 없이 상대 캐시를 무효화하면서 튕겨 냄.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이를 캐시 튕김(cache line bouncing) 또는 캐시 핑퐁(cache ping-poing) 문제임.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;즉, 여러 스레드 사이에 데이터 공유를 피할 수 있다면 가능한 한 피해야 함.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/393</guid>
      <comments>https://engineer-diary.tistory.com/393#entry393comment</comments>
      <pubDate>Mon, 27 May 2024 08:09:18 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 32일차 어떻게 캐시 친화적인 프로그램을 작성할까?</title>
      <link>https://engineer-diary.tistory.com/392</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최신 컴퓨터 시스템에서 프로그램이 메모리에 접근할 때 캐시의 적중률이 매우 중요함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 친화적인 프로그램을 작성하여 캐시 적중률을 향상 시켜야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;프로그램 지역성의 원칙&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;지역성이란 프로그램이 &amp;lsquo;매우 규칙적으로&amp;rsquo; 메모리에 접근한다는 의미임.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램이 메모리 조각에 접근하고 나서 이 조각을 여러 번 참조하는 경우 &amp;rarr; 시간적 지역성(temporal locality) 라고 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간적 지역성은 캐시 친화성이 매우 높음.&lt;/li&gt;
&lt;li&gt;데이터가 캐시에 있는 한 메모리에 접근하지 않아도 반복적으로 캐시의 적중이 가능함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로그램이 메모리 조각을 참조할 때, 인접한 메모리도 참조할 수 있음. &amp;rarr; 공간적 지역성(spatial locality) 라고 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시가 적중하지 않으면 메모리의 데이터를 캐시에 적재해야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일반적으로 요청한 메모리의 인접 데이터도 함께 캐시에 저장되므로 프로그램이 인접 데이터에 접근할 때 캐시가 적중하게 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메모리 풀 사용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;메모리 풀 기술은 일반적으로 고성능 요구 사항이 있을 때만 사용됨.&lt;/li&gt;
&lt;li&gt;프로그램이 메모리에서 조각을 N개 할당받아야 할 경우, malloc 을 사용해서 할당 받으면 메모리 조각 N개가 힙 영역 이곳저곳에 흩어져 있을 가능성이 높음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공간적 지역성이 좋지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메모리 풀 기술은 커다란 메모리 조각을 미리 할당받음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이후에 메모리 요청하거나 해제할 때 더이상 malloc 을 거치지 않음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;malloc 은 복잡한 과정에 속하므로, 부담이 없어짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메모리 풀 초기화할 때 연속적인 메모리 공간을 할당받기에 매우 캐시 친화적임.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;struct 구조체 재배치&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#define SIZE 100000

struct List
{
    List* next;
    int arr[SIZE];
    int value;
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연결리스트 구현을 위한 구조체임
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 arr[SIZE] 배열 변수는 전혀 사용되지 않음.&lt;/li&gt;
&lt;li&gt;이때, next 포인터와 value 값이 배열 arr 에 의해 멀리 떨어져 있기에 공간적 지역성이 나빠질 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#define SIZE 100000

struct List
{
    List* next;
    int value;
    int arr[SIZE];
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따라서 next 포인터와 value 값을 함께 배치하면 캐시는 next 포인터가 있다면 매우 높은 확률로 value 값도 포함되어 있을 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;핫 데이터와 콜드 데이터의 분리&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#define SIZE 100000

struct List
{
    List* next;
    int value;
    struct Arr* arr;
};

struct Arr
{
    int arr[SIZE};
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;List 구조체의 배열을 Arr 구조체로 빼서 포인터를 가리키게 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 되면 연결리스트 노드 자체 저장 공간이 줄어듦.&lt;/li&gt;
&lt;li&gt;각 노드별 저장 공간 크기가 줄기에 캐시에 저장할 수 있는 노드가 늘어나고 캐시 적중률이 높아짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;여기서 arr 는 콜드 데이터이며 next 포인터와 value 값은 빈번한 접근이 일어나는 핫 데이터임.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;콜드 데이터와 핫 데이터를 서로 분리하면 더 나은 지역성을 얻을 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;캐시 친화적인 데이터 구조&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;지역성 원칙에서 배열이 연결 리스트 보다 나음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열은 하나의 연속된 메모리 공간에 할당되지만, 연결 리스트는 일반적으로 이곳저곳에 흩어져 있을 수 있기 때문.&lt;/li&gt;
&lt;li&gt;하지만, 연결리스트의 자료구조 특성이 배열과 다르고, 캐시 친화적인것과 별개로 배열에서 얻을 수 없는 자료구조적 특성의 이점을 얻을 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;만약 연결리스트의 장점 (노드 추가, 삭제의 시간 효율)과 캐시 친화적이게 만들려면 연결 리스트 생성 시, 메모리 풀에서 메모리 요청하면 됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이러한 최적화를 할 때는 아래를 판단해야 함.&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;캐시의 적중률이 시스템 성능의 병목이 되는지 판단 해야 함&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;병목이 되지 않으면 굳이 최적화를 할 필요가 없음.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;다차원 배열 순회&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;다차원 배열의 경우 행 우선 방식으로 배열을 저장함.&lt;/li&gt;
&lt;li&gt;다차원 배열 순회 시, 행 우선 방식으로 접근한다면, 첫번째 데이터 조회 시, 캐시 적중에 실패하지만, 두번째 데이터 조회 시, 캐시가 적중됨.&lt;/li&gt;
&lt;li&gt;그러나 열 우선 방식으로 접근한다면, 캐시는 행 우선으로 캐시데이터를 가져오는데 순회를 열 우선으로 해버리니, 캐시를 아무리 갱신해도 절때 캐시 히트가 발생하지 않음.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/392</guid>
      <comments>https://engineer-diary.tistory.com/392#entry392comment</comments>
      <pubDate>Fri, 24 May 2024 03:41:13 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 31일차 캐시, 어디에나 존재하는 것</title>
      <link>https://engineer-diary.tistory.com/391</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램이 실행되는 동안 CPU는 메모리와 빈번하게 상호작용 해야 함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐시, 어디에나 존재하는 것&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;폰 노이만 구조에서는 CPU가 실행하는 기계 명령어와 명령어가 처리하는 데이터가 모두 메모리에 저장되어 있어야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하지만 레지스터 용량은 극히 제한되어있기에, CPU는 반드시 빈번히 메모리에 접근하여 명령어의 데이터를 가져와야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;또 명령어 실행 결과도 메모리에 다시 기록해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CPU와 메모리 속도가 서로 잘 맞는지 확인해야 함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU와 메모리의 속도 차이&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;시스템 성능의 속도가 상대적으로 느린 쪽에 맞추어 제한됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU와 메모리의 속도가 같아야 가장 좋은 성능을 발휘할 수 있는 나무통 원리(cannikn law)를 만족함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;하지만, CPU와 메모리는 시간이 지날 수록 속도 차이가 남.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;속도가 미친듯이 빠른 CPU는 명령어를 실행할 때 어쩔 수 없이 느릿느릿한 메모리를 기다릴 수밖에 없음.&lt;/li&gt;
&lt;li&gt;일반적인 시스템에서 메모리의 속도는 CPU의 100분의 1에 불과함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;도서관, 책상, 캐시&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;도서관에서 책을 가져온 후에는 다시 특정 자료를 찾을 때 일이 훨씬 쉬움.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;책상위에 책이 놓여있기에 바로 조사하면 됨.&lt;/li&gt;
&lt;li&gt;책상은 캐시(cache)에 비유할 수 있고, 서가는 메모리에 비유할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최신 CPU는 메모리 사이에 캐시 계층이 추가되어 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시는 가격이 비싸고 용량이 제한적이지만 접근 속도가 거의 CPU 속도에 필적함.&lt;/li&gt;
&lt;li&gt;캐시 안에 최근 메모리에서 얻은 데이터가 저장되며 CPU는 메모리에서 명령어와 데이터를 꺼내야 할 때도 무조건 먼저 캐시에서 해당 내용을 찾음.&lt;/li&gt;
&lt;li&gt;캐시가 적중하면 메모리에 접근하지 않고 CPU가 명령어 실행하는 속도를 크게 끌어올릴 수 있음.&lt;/li&gt;
&lt;li&gt;또, CPU가 더이상 직접 메모리를 읽고 쓰지 않기에 CPU 와 메모리 속도 차이도 보완할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일반적으로 x86 같은 최신 CPU와 메모리 사이에 실제로 세 단계의 캐시가 추가되어 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;L1 캐시 접근 속도는 레지스터 접근 속도에 비해 약간 느리지만 거의 대동소이 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대략 4클럭 주기가 소요됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;L2 캐시 접근속도는 대략 10클럭 주기가 소요됨.&lt;/li&gt;
&lt;li&gt;L3 캐시의 접근 속도는 대략 50클럭 주기가 소요됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시 단계에 따라 접근 속도는 낮아지지만 용량이 증가함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;L1, L2, L3 캐시, CPU 코어는 레지스터 칩 내에 묶여 패키징(packaging) 되어 있음.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;CPU &amp;rarr; L1 캐시 &amp;rarr; L2 캐시 &amp;rarr; L3 캐시 &amp;rarr; 메모리&amp;rdquo; 순서대로 데이터를 캐시 히트, 미스에 따라 가져오게 됨.&lt;/li&gt;
&lt;li&gt;캐시는 컴퓨터 시스템 성능을 향상 시키는데 매우 중요함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오늘날 CPU 칩에 상당 부분의 공간을 캐시가 차지하고 있고, 실제로 기계 명령어를 실행하는 CPU 코어 공간은 크지 않음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공짜 점심은 없다: 캐시 갱신&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;시스템 성능이 극적으로 향상된 만큼 대가가 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리에 기록할 때 나타남.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;캐시가 있기에 CPU는 더 이상 메모리와 직접 일하지 않음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU는 캐시에 직접 기록함&lt;/li&gt;
&lt;li&gt;캐시의 데이터는 갱신 되었지만, 메모리 데이터는 아직 예전 것으로 불일치 문제가 발생함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 문제를 해결하려면 캐시 갱신할 때 메모리도 함께 갱신해야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;근데 이러면 CPU가 결국 메모리 갱신될 때까지 대기해야 함. &amp;rarr; 동기실 설계 방법임.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CPU가 메모리에 기록할 때는 캐시를 직접 갱신하지만 이때 반드시 메모리가 갱신이 완료되기를 기다릴 필요 없이 CPU는 계속해서 다음 명령어를 실행할 수 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리가 업데이트 되는 시점은 캐시 용량이 부족한 경우임.&lt;/li&gt;
&lt;li&gt;캐시에서 자주 사용되지 않는 데이터를 제거해야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시에서 제거된 데이터가 수정된 적이 있다면 이를 메모리에 갱신해야 함.&lt;/li&gt;
&lt;li&gt;이렇게 캐시의 갱신과 메모리 갱신이 분리됨 (비동기 방식)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세상에 공짜 저녁은 없다: 다중 코어 캐시와 일관성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;단일 CPU 성능은 무어의 법칙으로 더 이상 향상 시키기 어려움.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다중 코어를 활용하는 방향으로 감&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다중 코어를 최대한 활용하는 다중 스레드 or 다중 프로세스가 없다면 다중 코어의 위력을 충분히 활용할 수 없음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다중 스레드 프로그램을 작성하는건 프로그래머에게 어려운 일임.&lt;/li&gt;
&lt;li&gt;소프트웨어 계층 뿐만 아니라 하드웨어 계층에도 어느 정도 어려움이 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU가 코어 여러 개를 가지면 코어 별로 캐시를 가지게 되는데, 각 코어별 캐시 데이터가 불일치 문제가 발생함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 문제를 해결하려면 캐시 한 개에서 갱신된 변수가 다른 CPU 코어의 캐시에 존재한다면 이 캐시도 함께 갱신되어야 함.&lt;/li&gt;
&lt;li&gt;최신 CPU에 고전적인 MESI 규칙같은 다중 코어 캐시 일관성을 유지하는 규칙이 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빈번하게 다중 코어 캐시의 일관성을 유지하면 성능에 대가를 따름.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/391</guid>
      <comments>https://engineer-diary.tistory.com/391#entry391comment</comments>
      <pubDate>Thu, 23 May 2024 03:07:47 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 30일차 CPU, 스택과 함수 호출, 시스템 호출, 스레드 전환, 인터럽트 처리 통달하기 (2)</title>
      <link>https://engineer-diary.tistory.com/390</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;함수 호출과 실행 시간 스택&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;함수를 호출할 때, CPU가 호출된 함수의 첫 번째 기계 명령어로 점프한 이후 함수 실행이 완료되면 다시 원래 위치로 점프해야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 상태의 보존과 복원을 포함해야함.&lt;/li&gt;
&lt;li&gt;보존해야하는 상태 정보에는 반환 주소 뿐만 아니라 사용한 레지스터 정보도 포함됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 A가 함수 B를 호출할 때 실행 정보는 함수 A 스택프레임에 저장됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 B가 실행 완료되면 스택 프레임 정보를 기반으로 함수 A의 실행이 재개됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시스템 호출과 커널 상태 스택&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;디스크 파일을 읽고 쓰거나 새로운 스레드 생성할 때, 누가 파일을 읽고 쓰는 작업을 하는가? 누가 스레드를 생성하는가?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;운영체제&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ex) open 함수 호출 &amp;rarr; 운영 체제가 파일을 여는 작업을 진행함.&lt;/li&gt;
&lt;li&gt;응용 프로그램은 시스템 호출을 통해 운영 체제에 서비스를 요청함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영 체제 역시 내부적으로 요청을 처리하는 함수를 호출해야 함.&lt;/li&gt;
&lt;li&gt;이 함수를 호출할 때는 &amp;lsquo;실행 시간 스택&amp;rsquo;이 필요함.&lt;/li&gt;
&lt;li&gt;이 실행 시간 스택은 &amp;lsquo;커널 상태 스택(kernel mode stack)&amp;rsquo;에 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용자 상태 스레드는 커널 상태에 대응하는 커널 상태 스택을 가지고 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 스레드가 운영 체제의 서비스를 요청해야 할 경우 시스템 호출을 사용해야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 시스템 호출은 특정 기계 명령어에 대응됨 (ex : 32비트 x86 에서 INT 명령어)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;CPU가 해당 명령어를 사용할 때 사용자 상태에서 커널 상태로 전환됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널 상태에서 사용자 상태 스레드에 대응하는 커널 상태 스택을 찾아서 여기에서 대응하는 커널 코드를 실행하여 시스템 호출 요청을 처리함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;여기서 사용자 상태 스레드의 레지스터 정보와 같은 &amp;lsquo;실행 상황 정보&amp;rsquo;는 커널 상태 스택에 저장됨.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;시스템 호출이 완료되면 커널 상태 스택에 저장된 사용자 상태 프로그램의 상황 정보에 따라 CPU 상태가 복원됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커널 상태에서 사용자 상태로 전환됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인터럽트와 인터럽트 함수 스택&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;컴퓨터가 프로그램을 실행하는 도중에 키보드의 키 입력, 마우스 움직임, 네트워크 수신 작업을 처리할 수 있는 것은 모두 &lt;b&gt;인터럽트 작동 방식&lt;/b&gt;을 이용하여 처리되기 때문임&lt;/li&gt;
&lt;li&gt;인터럽트는 현재 CPU 실행 흐름을 끊고 특정 인터럽트 처리 함수로 점프함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터럽트 처리 함수의 실행이 완료되면 원래 위치로 다시 점프함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터럽트 처리 함수 역시 함수이므로 일반 함수와 마찬가지로 &amp;lsquo;실행 시간 스택&amp;rsquo;이 있어야 함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터럽트 처리 함수에 자체적인 실행 시간 스택이 없는 경우, 인터럽트 처리 함수는 커널 상태 스택을 이용하여 인터럽트 처리함.&lt;/li&gt;
&lt;li&gt;인터럽트 처리 함수에 인터럽트 처리 함수(interrupt service routine) 스택, 즉 ISR 스택이라는 자체적인 실행 시간 스택이 있는 경우가 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터럽트 처리는 CPU 이기 때문에 모든 CPU가 자신만의 인터럽트 처리 함수 스택을 가짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터럽트 처리 함수와 시스템 호출은 비교적 유사하지만, 시스템 콜은 사용자 상태 프로그램이 직접 실행하고, 인터럽트 처리는 외부 장치로 실행됨.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터럽트가 발생하면 프로그램 실행이 일시적으로 중단되고 인터럽트 처리 함수로 점프함.&lt;/li&gt;
&lt;li&gt;이후는 시스템 호출과 유사함. (CPU가 사용자 상태 &amp;rarr; 커널 상태 전환 &amp;rarr; 사용자 상태 스레드에 대응하는 커널 상태 스택 찾음 &amp;rarr; &amp;hellip;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/390</guid>
      <comments>https://engineer-diary.tistory.com/390#entry390comment</comments>
      <pubDate>Wed, 22 May 2024 08:00:48 +0900</pubDate>
    </item>
    <item>
      <title>책너두 (컴퓨터 밑바닥의 비밀) 29일차 CPU, 스택과 함수 호출, 시스템 호출, 스레드 전환, 인터럽트 처리 통달하기 (1)</title>
      <link>https://engineer-diary.tistory.com/389</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터 시스템에는 함수 호출, 시스템 호출, 프로세스 전환, 스레드 전환, 인터럽트 처리와 같은 구조들이 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 호출을 통해 프로그래머는 코드 재사용성을 개선할 수 있음.&lt;/li&gt;
&lt;li&gt;시스템 호출로 프로그래머는 운영체제에 요청을 보낼 수 있음.&lt;/li&gt;
&lt;li&gt;프로세스와 스레드 전환으로 다중 작업이 가능함&lt;/li&gt;
&lt;li&gt;인터럽트 처리로 운영 체제가 외부 장치를 관리하게 할 수 있음.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이러한 구조는 컴퓨터 시스템의 기반이 됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;레지스터&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;레지스터를 사용하는 이유는 바로 속도 때문임.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU가 메모리에 접근하는 속도는 레지스터에 접근하는 속도의 대략 100분의 1정도임.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사실 레지스터와 메모리는 본질적 차이가 없음. 둘 다 정보를 저장하는데 사용함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단지 레지스터의 읽기 쓰기 속도가 훨씬 빠르고 제조 비용도 훨씬 비싸기에 용량에 한계가 있을 뿐임.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스택 포인터 (스택 레지스터)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;실행되는 모든 함수는 스택 프레임을 가짐.&lt;/li&gt;
&lt;li&gt;스택의 가장 중요한 정보는 스택 상단(stack top)임
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스택 상단 점보는 스택 하단(stack bottom)으로 함수 호출 스택의 추적이 가능함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 실행 시 함수에 정의된 로컬 변수와 전달된 매개변수 등을 저장하는 독립적인 메모리 공간이 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 독립적인 메모리 공간을 스택 프레임(stack frame)이라고 함.&lt;/li&gt;
&lt;li&gt;함수 호출 단계가 깊어질수록 스택 프레임 수도 증가하며 함수 호출이 완료되면 함수 호출의 반대 순서로 스택 프레임 수가 줄어듬.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 실행 시간 스택은 프로그램 실행 상태 중 가장 중요한 정보에 해당함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이외에도 &amp;lsquo;지금 어떤 명령어가 실행하고 있는지&amp;rsquo; 에 대한 정보도 매우 중요함 &amp;rarr; 명령어 주소 레지스터가 가지고 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;명령어 주소 레지스터&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;프로그램 카운터(program counter) 줄여서 PC 라고 부르기도 함.&lt;/li&gt;
&lt;li&gt;x86 에서는 명령어 포인터 (instruction pointer) 줄여서 IP라고 부르기도 함.&lt;/li&gt;
&lt;li&gt;프로그래머가 고급 언어로 프로그램을 작성하면 컴파일러는 일련의 기계 명령어를 생성함.&lt;/li&gt;
&lt;li&gt;CPU는 메모리에 기계 명령어로 가득찬 부분중 어떤 명령어를 실행하는 지 어떻게 하는가?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램이 실행되면 첫 번째로 실행할 기계 명령어의 주소가 PC 레지스터에 저장됨.&lt;/li&gt;
&lt;li&gt;CPU는 이 PC 레지스터에 저장되어 있는 주소에 따라 메모리에서 명령어를 가져와서 실행함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일반적으로 명령어는 순차적으로 실행함.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어 이전(if 문과 같은 분기 점프, 함수 호출 반환)과 관련된 일부 기계 명령어는 새로운 PC 레지스터에 저장함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 레지스터&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;x86 구조에서 이를 FLAGS 레지스터라고 함&lt;/li&gt;
&lt;li&gt;ARM 구조에서는 응용 프로그램 상태 레지스터라고 함.&lt;/li&gt;
&lt;li&gt;ex) 산술 연산 시 자리 올림수가 발생하거나 오버플로가 발생할 때 이런 정보를 상태 레지스터에 저장함.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Book/컴퓨터 밑바닥의 비밀</category>
      <author>wu2ee</author>
      <guid isPermaLink="true">https://engineer-diary.tistory.com/389</guid>
      <comments>https://engineer-diary.tistory.com/389#entry389comment</comments>
      <pubDate>Tue, 21 May 2024 09:40:23 +0900</pubDate>
    </item>
  </channel>
</rss>