상세 컨텐츠

본문 제목

CS:APP | Chapter 1 | 컴퓨터 시스템 overview

본문

CSAPP 1장의 각 소단원을 읽으면서 주요 내용과 추가적으로 알아본 정보들을 기록하는 포스팅😎

1장은 컴퓨터 시스템 전반을 얕고 넓게 훑는 챕터이다.

 

글자색이 다른 부분은 내가 따로 추가한 생각 혹은 정보이다 (= 틀릴 수도 있다)

 


1.1 정보는 비트와 컨텍스트로 이루어진다

  • 소스 프로그램은 byte(= 8 bit) 단위로 구성된다.
  • 대부분의 컴퓨터 시스템은 text 문자를 아스키 표준을 사용하여 표시한다.
    • 아스키 표준은 각 문자를 byte 길이의 정수 값으로 나타낸다. 

  • 텍스트 파일: hello.c 처럼 아스키 문자들로만 이루어진 파일
  • 바이너리 파일: 텍스트 파일을 제외한 다른 모든 파일
  • 컨텍스트(context)
    • 모든 시스템 내부의 정보는 bit들로 표시됨. 서로 다른 객체들을 구분하는 유일한 방법은 이들을 바라보는 컨텍스트에 의해서.
    • 컨텍스트에 따라 동일한 일련의 바이트가 정수, 부동소수, 문자열, 기계어 명령 등 다른 의미로 해석된다. 

 

1.2. 프로그램은 다른 프로그램에 의해 다른 형태로 번역된다

  • 저급 언어(Low-Level Language)
    • 하드웨어 접근: 저급 언어는 하드웨어에 직접 접근할 수 있으며, 특정 하드웨어 아키텍처에 맞춰 최적화될 수 있다.
    • 효율성: 고급 언어보다 실행 속도는 빠르다. 그러나 인간친화적이 아니기에 코드 작성과 유지 관리가 어렵다.
    • 메모리 관리: 프로그래머가 직접 메모리를 관리해야 한다.
  • 고급 언어(High-Level Language)
    • 추상화: 프로그래밍 요소와 구조를 사람이 이해하기 쉽도록 추상화되어 있다. 기계 코드보다 더 인간친화적이다.
    • 플랫폼 독립성: 대부분의 고급 언어는 다양한 하드웨어 및 운영 시스템에서 실행될 수 있도록 설계되어 있다.
    • 메모리 관리: 자동 메모리 관리 기능이 있는 경우가 많다. 
언어 분류 특징
기계어
(Machine Language)
저급 언어 (Low-Level) 컴퓨터 하드웨어가 직접 이해할 수 있는 이진 코드로 작성됨
어셈블리어
(Assembly Language)
저급 언어 (Low-Level) 기호적 명령어를 사용하여 프로그래밍함
C 언어 중간 수준 언어 저급과 고급 언어의 특징을 모두 갖춤, 하드웨어에 접근하고 시스템 프로그래밍을 할 수 있음
Java 고급 언어 (High-Level) 플랫폼 독립성과 객체 지향 프로그래밍을 지원함
파이썬 (Python) 고급 언어 (High-Level) 간결하고 읽기 쉬운 코드를 작성할 수 있으며, 다양한 라이브러리와 프레임워크를 지원함

위에서 아래로 갈수록 low level -> high level

 

  • 위에서 예시로 든 hello.c를 시스템에서 실행시키려면, 각 C 문장들은 다른 프로그램들에 의해 저급 기계어 인스트럭션들로 번역되어야 한다.
    • 소스 코드가 어떤 언어로 작성되었든, 결국 기계어로 번역해야 컴퓨터가 이를 이해하고 명령을 수행할 수 있다.
  • 번역: 4단계를 거쳐 실행된다. 1) 전처리, 2) 컴파일, 3) 어셈블리, 4) 링크
    • C 기준으로, 각 단계를 수행하는 프로그램을 1) 전처리기(cpp), 2) 컴파일러(cc1), 3) 어셈블러(as), 4) 링커(ld)라고 한다.
      1. 전처리: cpp는 본래의 C 프로그램을 #문자로 시작하는 directive에 따라 수정한다.
      2. 컴파일: cc1은 텍스트파일 hello.i를 텍스트파일인 hello.s로 번역하며, 이 파일에는 어셈블리어 프로그램이 저장된다.
      3. 어셈블리: as가 hello.s를 기계어 인스트럭션으로 번역하고, 이들을 재배치가능 목적프로그램의 형태로 묶어서 hello.o라는 목적파일에 그 결과를 저장한다.
      4. 링크: ld가 호출된 함수가 들어있는 파일과 미완성 실행파일을 통합한다. 그 결과는 hello 파일은 실행파일로 메모리에 적재되어 시스템에 의해 실행된다. 

각 단계에 대한 예시를 chatGPT에게 달라고 하니 다음과 같이 알려준다.


1. 전처리 (Preprocessing):

 

- 소스 코드 (source.c)

#include <stdio.h>
#define GREETING "Hello, World!"

int main() {
    printf("%s\\n", GREETING);
    return 0;
}

 

- 전처리기가 #include와 #define 지시어를 처리하면, 코드는 다음과 같이 변경됩니다:

// 내용은 stdio.h에서 가져옵니다...
int main() {
    printf("Hello, World!\\n");
    return 0;
}

 

 

2. 컴파일 (Compilation):

컴파일러는 전처리된 소스 코드를 어셈블리 코드로 변환합니다.

 

- 어셈블리 코드 (source.s) (간략화된 예):

.section .data
.string "Hello, World!\\n"

.section .text
.globl main
main:
    movl $message, %edi
    call printf
    ret

 

3. 어셈블리 (Assembly):

어셈블러는 어셈블리 코드를 기계어로 변환하여 목적 파일을 생성합니다.

 

- 목적 파일 (source.o): (이진 형식으로, 일부는 ASCII로 표시됩니다)

00000000: 4865 6c6c 6f2c 2057 6f72 6c64 210a 0000  Hello, World!...
...
00000010: b800 0000 00e8 0000 0000 c3           ............

 

4. 링킹 (Linking):

링커는 목적 파일과 필요한 라이브러리를 결합하여 실행 가능한 프로그램을 생성합니다.

 

- 실행 가능한 파일 (executable): (이진 형식으로, 일부는 ASCII로 표시됩니다)

00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
...
00001000: 4865 6c6c 6f2c 2057 6f72 6c64 210a       Hello, World!.

 

이렇게 각 단계를 거쳐 C 소스 코드는 최종적으로 실행 가능한 프로그램으로 변환됩니다. 

 


1.3 컴파일 시스템이 어떻게 동작하는지 이해하는 것은 중요하다

  • 컴파일 시스템이 어떻게 동작하는지 이해해야 하는 중요한 이유들
    • 프로그램 성능 최적화: 컴파일러가 어떻게 C(또는 다른 언어의) 문장들을 기계어 코드로 번역하는지 알 필요가 있다. 예를 들어 while 루프는 for 루프보다 더 효율적일까? 수식 연산시 괄호를 단순히 재배치하기만 해도 함수가 더 빨리 실행되는 이유는 무엇인가? 
    • 링크 에러 이해: 가장 당혹스러운 프로그래밍 에러는 링커의 동작과 관련되어 있으며, 큰 규모의 소프트웨어 시스템을 빌드하려는 경우에 더욱 그렇다. 

 

1.4 프로세서는 메모리에 저장된 인스트럭션을 읽고 해석한다.

  • 실행파일을 유닉스 시스템에서 실행하기 위해서 쉘이라는 응용프로그램에 그 이름을 입력한다.
    • 쉘은 커맨드라인 인터프리터로 프롬프트를 출력하고, 명령어 라인을 입력받아 그 명령을 실행한다.
    • 만일 명령어 라인이 내장 쉘 명령어가 아니면 쉘은 실행파일의 이름으로 판단하고 그 파일을 로딩해서 실행해준다.

 

  • 전형적인 시스템의 하드웨어 구성
    • 버스(Buses)
      • 시스템 내를 관통하는 전기적 배선군. 컴포넌트들 간에 byte 정보를 전송한다.
      • 일반적으로 워드(word)라고 하는 고정 크기의 byte 단위로 데이터를 전송하도록 설계된다. (오늘날 대부분 컴퓨터들은 4byte(32 bit) 또는 8바이트(64 bit) 워드 크기를 갖는다.)
    • 입출력 장치(I/O)
      • 시스템과 외부세계와의 연결을 담당. 
    • 메인 메모리
      • 물리적으로 메인 메모리는 DRAM들로 구성
      • 논리적으로 메모리는 연속적인 byte들의 배열. 각각 0부터 시작해서 고유의 주소(배열의 인덱스)를 가지고 있다.
    • 프로세서(CPU)
      • 메인 메모리에 저장된 인스트럭션들을 해독(실행)하는 엔진
        1. 프로세서는 PC가 가리키는 메모리로부터 인스트럭션을 읽어오고
        2. 이 인스트럭션에서 bit들을 해석하여 인스트럭션이 지정하는 간단한 동작을 실행하고
        3. PC를 다음 인스트럭션 위치로 업데이트한다.
      • 프로세서 중심에는 워드 크기의 저장장치(레지스터)인 프로그램 카운터(PC)가 있다.


32 bit vs 64 bit 

일반적으로 32 bit와 64 bit의 차이를 물어볼 때, 그 대상은 CPU 아키텍처 혹은 운영체제 아키텍처를 말한다.

각각에 있어서 위 질문의 대답은 다음과 같다.

특징 32bit CPU 아키텍처 64bit CPU 아키텍처
버스 너비 데이터 버스와 주소 버스 각각 32비트 데이터 버스와 주소 버스 각각 64비트
메모리 주소 지정 최대 2^32개의 고유한 메모리 주소, 최대 4GB 메모리 지원 최대 2^64개의 고유한 메모리 주소, 매우 큰 양의 메모리 지원
레지스터 크기 32비트 레지스터 사용 64비트 레지스터 사용
데이터 처리 능력 더 낮은 메모리 용량과 데이터 처리 능력 더 높은 메모리 용량과 데이터 처리 능력, 더 큰 데이터 세트와 더 복잡한 애플리케이션 처리 가능

 

특징 32bit 운영체제 64bit 운영체제
메모리 주소 지정 32비트 메모리 주소 사용, 최대 4GB 메모리 지원 64비트 메모리 주소 사용, 매우 큰 양의 메모리 지원
애플리케이션 실행 32비트 애플리케이션만 실행, 최대 2GB 메모리 할당 가능 64비트 및 32비트 애플리케이션 실행, 매우 큰 양의 메모리 할당 가능
시스템 리소스 사용 더 낮은 시스템 리소스 사용, 더 낮은 메모리 용량과 데이터 처리 능력 더 높은 시스템 리소스 사용, 더 높은 메모리 용량과 더 큰 데이터 처리 능력

 

 

1.5 캐시가 중요하다

  • hello 프로그램의 기계어 인스트럭션들은 본래 하드디스크에 저장 -> 프로그램이 로딩될 때 메인 메모리로 복사 -> 프로세서가 프로그램을 실행할 때 프로세서로 복사
  • 더 큰 저장장치들은 보다 작은 저장장치들보다 느린 속도를 갖는다.
    • 일반적인 레지스터 파일은 수백 byte의 정보를 저장 << 메인 메모리의 경우 십억 byte 저장
    • 그러나 프로세서는 레지스터 파일의 데이터를 읽는 메모리 대비 100배 더 빠르게 읽을 수 있다
  • 반도체 기술 발달에 따라 프로세서-메모리 간 격차는 지속적으로 증가
    • 메인 메모리 속도를 높이는 것보다 프로세서 속도를 높이는 게 더 쉽고 저비용
  • 이를 보완하기 위해 '캐시 메모리'라는 저장장치 고안
    • L1 캐시: 프로세서 칩 내에 존재. 수천 byte의 데이터 저장 가능. 거의 레지스터 파일만큼 빠른 속도로 접근 가능.
    • L2 캐시: 수백 kb ~ 수 mb 용량. 프로세서와 전용 버스로 연결
    • L1, L2는 SRAM 하드웨어로 구현됨.
  • 자주 접근할 가능성이 높은 데이터를 캐시가 보관하도록 설정 -> 빠른 캐시를 이용해서 대부분의 메모리 작업을 수행할 수 있음
  • 이 책의 가장 중요한 교훈 중 하나: 캐시 메모리를 이해하는 응용 프로그래머는 캐시를 활용하여 자신의 프로그램 성능을 10배 이상 개선 가능

 

1.6 저장장치들은 계층구조를 이룬다

  • 사실, 모든 컴퓨터 시스템의 저장장치들은 메모리 계층구조로 구성되어 있음
  • 계층의 꼭대기 -> 맨 밑바닥으로 갈수록 저장장치들은 더 느리고, 더 크고, byte 당 가격이 저렴해진다. 

메모리 계층구조의 각 저장장치 설명 + 어디에 위치하는지

  위치 설명
Register CPU 코어 내부 레지스터는 CPU 코어 내부에 위치하며, 가장 빠른 데이터 접근을 제공.
레지스터는 연산 중에 사용되는 데이터와 주소를 임시로 저장하는 데 사용된다.
L1 Cache CPU 코어 내부 L1 캐시는 CPU 코어 내부에 위치하며, 매우 빠른 데이터 접근을 제공.
자주 사용되는 데이터와 명령어를 저장하여 CPU의 성능을 향상시킨다.
L2 Cache CPU 코어 내부 L2 캐시도 CPU 코어 내부에 위치하며, L1 캐시보다 약간 느리지만 여전히 빠른 데이터 접근을 제공한다.
L3 Cache CPU 코어 외부, CPU 칩 패키지 내부 L3 캐시는 CPU 코어 외부에 위치하지만 칩 패키지 내부에 있으며, 모든 코어가 공유한다.
L3 캐시는 L1 및 L2 캐시의 일관성을 유지하고 캐시 미스를 줄이는 데 도움이 된다.
Main Memory (RAM) CPU 칩 외부 메인 메모리는 CPU 칩과 별개의 주요 구성 요소로, 시스템의 주요 데이터 저장 영역으로 작동한다.
CPU는 메인 메모리로부터 데이터를 읽고 쓰기 위해 메모리 버스를 사용한다.
SSD CPU 칩 외부 SSD는 CPU 칩 외부에 위치하며, 데이터를 비휘발성으로 저장한다.
메인 메모리보다는 느리지만, 전원이 꺼져도 데이터를 유지할 수 있으며, 전통적인 하드 드라이브보다 빠른 데이터 접근을 제공한다.
분산 파일 시스템/ 웹서버 네트워크를 통해 연결된 서버들 상에 위치 분산 파일 시스템은 여러 서버에 걸쳐 데이터를 저장하고 관리한다.
이는 데이터의 신뢰성과 가용성을 높이며, 클라우드 환경에서 효율적인 데이터 저장 및 공유를 가능하게 한다.

웹 서버는 HTTP 프로토콜을 사용하여 클라이언트의 요청을 처리하고 웹 페이지를 제공한다.
웹 서버는 네트워크에 연결된 서버 상에 위치하며, 클라우드 환경에서도 실행될 수 있다.

 

  • 메모리 계층구조의 주요 아이디어는 한 레벨의 저장장치가 다음 하위레벨 저장장치의 캐시 역할을 한다는 것이다.
    • L1 <- L2의 캐시, L2 <- L3의 캐시, L3 캐시 <- 메인 메모리의 캐시, ...
    • (분산 파일시스템을 가지는 네트워크 시스템에서) 로컬 디스크 <- 다른 시스템의 디스크에 저장된 데이터의 캐시
      • 로컬 디스크가 다른 시스템의 디스크에 저장된 데이터의 캐시 역할을 하는 것은 분산 파일 시스템의 특징 중 하나로, 이는 데이터의 로컬 복사본을 유지하여 네트워크 대역폭을 절약하고 데이터 접근 속도를 높이는 데 도움이 된다고 한다.
    • 유튜브, 넷플릭스 등 글로벌 서비스들은 각 대륙과 주요 국가마다 데이터센터를 설치해놓는다. 사용자에게 더 빠른 서비스를 제공하고, 네트워크 지연을 줄이며, 글로벌 트래픽을 더 효율적으로 관리하기 위한 방법인데, 이 또한 이러한 아이디어의 확장이라고 볼 수 있다.

구글 클라우드 데이터 센터의 위치 (출처: https://www.google.com/about/datacenters/locations/)

 

<아래는 chatGPT가 제안한 해당 주제와 관련해서 추가로 고려할 점들>

- 데이터 일관성: 캐시 레벨 간에 데이터 일관성을 유지하는 것이 중요합니다. 예를 들어, 한 레벨의 캐시에서 데이터를 수정하면, 이 변경 사항이 다른 캐시 레벨과 동기화되어야 합니다.

- 캐시 정책: 어떤 데이터를 캐시에 유지할지, 언제 캐시를 새로 고칠지 결정하는 캐시 정책이 중요합니다. 이는 시스템의 성능과 리소스 사용률에 큰 영향을 미칩니다.

- 비용과 성능의 트레이드오프: 더 높은 레벨의 캐시는 일반적으로 더 높은 성능을 제공하지만 더 많은 비용이 듭니다. 이러한 트레이드오프를 이해하고 적절한 설계 결정을 내리는 것이 중요합니다.

 

 

1.7 운영체제는 하드웨어를 관리한다

 

  • 응용프로그램이 하드웨어를 제어하려면 언제나 운영체제를 통해서 해야 한다. 
  • 운영체제는 두 가지 주요 목적을 가지고 있다.
    1. 제멋대로 동작하는 응용프로그램들이 하드웨어를 잘못 사용하는 것을 막기 위해
    2. 응용프로그램들이 단순하고 균일한 메커니즘을 활용하여 매우 다른 저수준 하드웨어 장치들을 조작할 수 있도록 하기 위해
  • 이 두 가지 목적들은 근본적인 추상화를 통해 달성된다. (프로세스, 가상메모리, 파일)
    • 파일: 입출력장치의 추상화
    • 가상메모리: 메인 메모리와 디스크 입출력장치의 추상화 
    • 프로세스: 프로세서, 메인 메모리, 입출력장치 모두의 추상화 결과
    • 가상머신: 운영체제, 프로세서, 프로그램 모두를 포함하는 컴퓨터 전체의 추상화

(1.10 컴퓨터 시스템의 계층화 모습) (1.11 운영체제에 의한 추상화)

추상화??

추상화는 복잡한 시스템을 단순화하여 이해하고 사용할 수 있게 만드는 기술적 방법입니다. 추상화를 통해, 사용자는 시스템의 내부 작동 방식에 대해 신경 쓰지 않고도 시스템을 사용할 수 있습니다.

1. 프로세스 추상화: 프로세서, 메인 메모리, 입출력 장치 등의 복잡한 상호 작용을 숨기고, 사용자에게 단순한 실행 환경을 제공합니다. 예를 들어, 프로그래머는 프로세스가 독립적으로 실행되는 것처럼 느끼지만, 실제로는 운영체제가 여러 프로세스를 관리하며 스케줄링합니다.

2. 가상 메모리 추상화: 메인 메모리와 디스크의 복잡한 관리를 숨기고, 연속적이고 큰 메모리 공간을 제공함으로써 프로그래머가 메모리 관리를 더 쉽게 할 수 있게 합니다. 예를 들어, 프로그래머는 물리적 메모리의 위치에 대해 걱정하지 않고, 단순히 가상 메모리 주소를 사용할 수 있습니다.

3. 파일 및 입출력장치 추상화: 디스크, 네트워크 카드, 프린터 등 다양한 입출력 장치의 복잡한 동작을 숨기고, 일관된 인터페이스를 제공하여 프로그래머가 더 쉽게 입출력 작업을 수행할 수 있게 합니다. 예를 들어, 프로그래머는 파일을 읽고 쓰는 단순한 명령을 사용할 수 있으며, 운영체제가 실제로 어떻게 데이터를 저장하고 전송하는지에 대해 걱정할 필요가 없습니다.

이렇게 추상화는 프로그래머와 시스템 사용자에게 더 단순하고 이해하기 쉬운 인터페이스를 제공하며, 시스템의 내부 복잡성을 숨깁니다. 즉, 위 개념들은 실제로는 더 복잡한 하드웨어를 복잡하지 않은 것처럼 조작하기 위한 장치. 

 

  • 1. 프로세스(Process)
    • 프로세스는 실행 중인 프로그램에 대한 운영체제의 추상화
      • 특정 프로그램이 실행될 때, 운영체제는 시스템에서 이 한 개의 프로그램만 실행되는 것 같은 착각에 빠지도록 해준다. 즉, 프로그램이 프로세서, 메인 메모리, 입출력장치를 모두 독차지하고 있는 것처럼 보인다. 이러한 환상은 프로세스 라고 하는 개념에 의해 만들어진다. 
    • 다수의 프로세스들은 동일 시스템에서 '동시에(concurrently)' 실행될 수 있다. 
      • '동시에(concurrently)'라는 말은 한 프로세스의 인스트럭션들이 다른 프로세스의 인스트럭션들과 섞인다는 것을 의미
      • 대부분의 시스템에서 CPU보다 많은 수의 프로세스들이 존재
    • 문맥전환 (Context Switching): 프로세서가 프로세스들을 바꿔주는 방식으로 CPU가 다수의 프로세스를 동시에 실행하는 것처럼 보이게 해준다.
      • 문맥(Context): PC, 레지스터 파일, 메인 메모리의 현재 값 등 현재 실행 중인 프로세스의 상태 정보
      • 문맥 전환을 할 때, 현재 컨텍스트를 저장하고 다음 컨텍스트로 이동. 다시 돌아올 땐 저장한 컨텍스트를 넘겨줌. 그러면 이전에 실행 중이던 부분부터 다시 실행된다. 
    • 이는 커널(kernel)에 의해 관리됨.
      • 커널은 OS 코드의 일부분으로, 메모리에 상주 (별도의 프로세스는 아님)
    • 쓰레드(Thread)
      • 프로세스는 쓰레드라고 하는 다수의 실행 유닛으로 구성되어 있음. 

https://www.javatpoint.com/process-vs-thread

 

  • 2. 가상메모리(Virtual Memory)
    • 각 프로세스들이 메인 메모리 전체를 독점적으로 사용하고 있는 것 같은 환상을 제공하는 추상화
    • 가상주소공간
      • 최상위 영역: 모든 프로세스들이 공통으로 사용하는 OS의 코드, 데이터를 저장
      • 하위 영역: 사용자 프로세스의 코드, 데이터를 저장

프로세스의 가상주소 공간


메모리 heap vs 자료구조 heap // 메모리 stack vs 자료구조 stack

마침 자료구조들과 이름이 같아서, 서로 관련있는 개념인지 헷갈렸다. 그래서 알아봄

   기능
메모리 힙 (Heap) 프로그램의 실행 도중 동적으로 메모리를 할당하고 해제하는 영역이다. 구조화되지 않은 메모리 풀로, 프로그래머가 필요에 따라 메모리를 할당하고 해제할 수 있다.
메모리 스택 (Stack) 프로그램의 실행 흐름을 관리하는 영역으로, 함수 호출과 반환, 지역 변수의 저장 등을 처리한다. LIFO (Last In First Out) 방식으로 동작하며, 구조화된 방식으로 메모리를 할당/해제한다.

메모리 힙이 자료구조 힙으로 구현된 건 아니고, 마찬가지로 메모리 스택이 자료구조 스택으로 구현된 것도 아니다. 

 

  • 메모리 힙의 경우, "Heap"이 쌓여있는 더미 모양을 묘사하는 단어인데, 메모리 힙의 동작 방식이 이와 비슷해서 이름 붙여졌다. 자료구조 힙도 마찬가지로 그 나름대로 모양이 더미 모양이어서 그렇게 이름 붙었다.
  • 메모리 스택의 경우, 자료구조 stack의 원리를 기반으로 구현되어 있기는 하다. 그러나 자료구조 stack을 통해 구현되었다고 볼 수는 없다. 

  • 3. 파일 (File)
    • 파일은 더도 말고 덜도 말고 그저 연속된 바이트들 (?)
    • 디스크, 키보드, 디스플레이 등 모든 입출력장치는 파일로 모델링 (시스템의 모든 입출력은 유닉스 I/O라는 시스템 콜들을 이용하여 파일을 읽고 쓰는 형태로 이루어짐) 

 

 

1.8 시스템은 네트워크를 사용하여 다른 시스템과 통신한다

  • 최신 시스템들은 네트워크에 의해 다른 시스템과 종종 연결된다. 
  • 개별 시스템의 관점에서 볼 때, 네트워크는 단지 또 다른 입출력장치로 볼 수 있다.
    • 데이터를 로컬디스크 대신 네트워크를 통해서 다른 컴퓨터로 이동하고, 역으로 다른 컴퓨터로부터 받은 데이터를 메인 메모리에 복사
    • 이 과정이 사실 USB를 꽂는 행위와 시스템 입장에서는 차이가 없을 듯

 

1.9 중요한 주제들

  • Amdahl의 법칙
    • 시스템의 한 부분의 성능을 개선할 때, 1) 그 부분이 전체에서 어느정도를 차지하는가2) 얼마나 개선됐는가(빨라졌는가)로 계산하고 표현

  • Amdahl의 법칙 = Amdahl의 저주
    • 시스템의 60%를 차지하는 주요 부분의 속도를 3배 빨라지도록 개선한다고 해도 속도향상은 1/[0.4+0.6/3] = 1.67을 얻는다.
      (= 실질적인 개선을 하였음에도 총 속도향상은 비교적 적다.)

 

 

Amdahl의 법칙이 내게 준 인사이트는 두 가지

  1. 어떤 프로젝트의 성과를 말할 때, 해당 법칙에 기반해서 표현하면 훨씬 매끄러운 전달이 가능할듯
  2. 어떤 시스템 전체의 속도를 획기적으로 향상시키는 것은 수학적으로 매우 어려움을 알 수 있음. 

https://ko.wikipedia.org/wiki/%EC%95%94%EB%8B%AC%EC%9D%98_%EB%B2%95%EC%B9%99

과거 삼성전자가 위기에 빠졌을 때, 이건희가 다음과 같이 말한 일화는 유명하다. "마누라, 자식 빼고 다 바꿔!" 

그만큼 조직 전체의 효율성을 크게 개선한다는 것이, 속된 말로 전체를 뒤집어엎는 수준이 아니면 힘들다는 거다. 

 

그래서 혁신이 중요하다.

 

아무리 빠르게 성장해온 조직이라고 해도, 덩치가 커지면 자연스럽게 둔해질 수밖에 없다. 타성에 젖는 순간 효율성은 극도로 저하된다. 

이건 집단에도 적용되고 한 개인에게도 적용되는 문제같다. 

 

비록 컴퓨터과학에서 나온 개념이지만, 물이 고이면 썩는다는 세상의 이치를 수식으로 증명한 듯한(?) 그런 감명을 받았다. 

이상, 암달의 법칙을 본 문과의 감상 ..ㅎㅎ

 

 

 

 

관련글 더보기