컴퓨터 공부/파이썬 공부

고성능 파이썬(1)

냥냥펀치데스 2021. 6. 26. 17:01
728x90

 

연산장치

연산장치의 주요 속성은 한 사이클에 처리할수 있는 연산의 갯수와 1초에 처리할수 있는 사이클의 횟수이다.

한 사이클에 처리할수 있는 연산의 갯수는 IPC 로 측정하며 초당 사이클 횟수는 클럭 속도로 측정한다.

ex) [인텔 코어 시리즈 : IPC - ↑, 클럭속도 - ↓] ↔ [펜티엄4 : IPC - ↓, 클럭속도 - ↑]

=> GPU : IPC - ↑, 클럭속도 - ↑

클럭 속도 ↑ -> 초당 연산량 ↑ = IPC ↑ -> 벡터화 수준 ↑ => 처리 성능 ↑

CPU 가 여러 데이터를 한번에 처리할때 벡터화가 되는데 이런 종류의 명령을 SIMD 라고 한다.

하이퍼 스레딩 : 운영체제에 가상의 CPU 인식 -> 두 스레드를 번갈아 가며 실행하도록 하는 기법 => 최대 30%성능향상

비순차적 명령어 처리 : 이전 작업의 결과에 영향을 받지 않는 부분을 찾아내서 두 작업을 순서 관계 없이 or 동시 실행

파이썬은 GIL 때문에 다수의 코어를 사용하는 장점이 없으나 multiprocessing 모듈 or numpy, numexpr, 사이썬, 분산 컴퓨팅 모델을 사용하는 방법으로 해결가능하다.

통신 계층

버스의 변형

메모리 장치 : 읽기/쓰기 속도와 용량은 반비례 - 하드디스크 -> RAM -> L1/L2 캐시

ex) FSB : RAM ↔ L1/L2 캐시 연결 , 외부버스 : (CPU, 시스템 메모리) ↔ (외부 하드웨어)

속도 : RAM ↔ L1/L2 캐시 < CPU ↔ L1/L2 캐시 => 계산에 필요한 데이터를 캐시에 올리고 CPU 로 빠르게 제공

GPU를 사용하는데 걸림돌은 버스이다. GPU는 주변장치 이므로 일반적으로 FSB 보다 훨씬 느린 PCI 버스로 연결된다.

=> 이기종 컴퓨팅 또는 CPU 와 GPU 를 FSB 로 연결한 시스템은 전송비용을 줄여 GPU 로 사용할수 있도록 한다.

파이썬을 통해 구성 요소 살펴보기

# 특정 수가 소수인지 판별하는 코드

import math

def check_prime(number) :
    sqrt_number = math.sqrt(number)

    for i in range(2, int(sqrt_number) + 1) :
    if (number / i).is_integer() :
        return False
    return True

print(f"check_prime(10,000,000) = {check_prime(10_000_000)}")
# check_prime(10,000,000) = False
print(f"check_prime(10,000,019) = {check_prime(10_000_019)}")
# check_prime(10,000,019) = True

이상적인 컴퓨팅

RAM에 number 가 저장되고, sqrt_number 계산을 위해 이 값을 CPU 의 L1/L2 캐시에 저장하고, CPU 가 계산한 결과를 다시 RAM 으로 돌려준다. 이 시나리오는 RAM 에서 읽는 횟수를 최소한 하고 속도가 빠른 L1/L2 캐시를 사용하였기 때문에 이상적이다.

파이썬 인터프리터는 컴퓨터의 구성 요소를 추상화 하기 때문에 개발자가 생각할 필요가 없지만, 그만큼 성능상의 비용을 지불해야한다. 이에 프로파일링을 통해 코드의 느린부분을 찾아내고 더 효율적인 방법을 생각해야 한다.

파이썬의 추상화는 L1/L2 캐시에 유지해야 하는 최적화에 방해가 된다.

그 이유는 첫번째로 파이썬 객체가 최적화된 형태로 저장되지 않기 때문인데, 파이썬이 메모리를 자동할당하고 헤제하는 가비지 컬렉터를 사용하기 때문이다.

이는 CPU 캐시에 데이터를 전송하는데 영향을 미치는 메모리 단편화를 일으킨다. 또 메모리에 저장되는 자료구조를 변경할수 없기 때문에 버스 폭이 넓더라도 한번의 계산에 정보를 전부 전송할수 없다.

두번째로 파이썬은 동적 타입을 사용하며 컴파일되지 않는다.

세번째로 GIL이 코드를 병렬로 실행하려할때 성능을 낮춘다.

 

파이썬을 쓰는 이유

1. 파이썬은 표현력이 좋고 배우기 쉽다

2. 파이썬 라이브러리는 타 언어로 작성된 도구를 감싸서 다른 시스템을 쉽게 호출하다

3. 중요하고 안정적인 다수의 라이브러리와 도구를 기본으로 제공한 빠른 프로토타이핑(jupyter notebook)

 

모범적 작업 절차

1. 최상위 수준 README 파일 작성

2. 프로젝트 목적, 폴더 내용, 데이터 출처, 중요한 파일 목록, 프로그램과 파일의 실행 방법, 테스트 실행 방법 적기

3. 도커 사용을 통한 필요한 라이브러리 정확히 알려주기

4. 단위 테스트 추가 (pytest)

5. 코드의 모든 함수, 클래스, 모듈에 톡스트링 추가 => 달성하려는 내용 제대로 설명

6. 코드의 길이를 고려하여 리팩토링 하라

7. 소스 관리 -> 커밋 자주, 매일 리포지터리 작업 푸시

8. PEP8 코딩 표준(flake8 적용하여 소스코드를 린트 => 실수 방지)

9. 운영체제와 분리된 환경(아나콘다 or pipenv or 도커)

10. 시스템 자동화

11. 가독성