본문 바로가기

정보/프로그래밍

프로그램 실행 속도를 개선하는 방법 (중복 연산 제거, 벡터 연산, 병렬 처리)

오늘은 제가 프로그램 실행 속도를 개선했던 경험에 기반하여 몇 가지 팁을 알려드리려 합니다.

 

학부연구생을 하면서 데이터 처리와 같은 업무를 맡았는데 어떤 프로그램의 실행 시간이 과도하게 오래 소요되는 문제가 있었습니다.

 

이를테면 어떤 변수를 구하는 프로그램의 경우 약 2주 정도의 시간이 소요되었습니다.

 

제가 프로그램을 짜는 방법은 대체적으로 어떤 파생 변수를 구하는 함수를 만들고 중첩 for문 안에 넣는 방식이었습니다.

# 예시 python 코드
all_lst = []

for s in lst1:
    for r in lst1: 
        for i in lst2: 
            for j in lst2: 
                example = foo(s, r, i, j)
                all_lst.append(example)

 

연구에 사용할 데이터 셋이 이전의 데이터 셋보다 용량이 커지게 되면서 프로그램 실행 시간을 개선할 필요성을 느꼈습니다.

 

제가 위와 같은 프로그램 코드를 개선한 방법에 대하여 쉬운 것부터 알려드리려 합니다.

 

R로 진행하였지만 다른 프로그래밍 언어에서도 유사하게 진행할 수 있는 방법들입니다.

 

저와 같은 문제에 직면하신 분들에게 아이디어를 제공하는 목적이기 때문에 구체적인 코드보다는 방법론 위주로 소개하겠습니다.

 

 

중복 연산 제거


위의 방법은 실행 속도를 개선하는 방법 중 제가 가장 먼저 떠올린 방법입니다.

 

위의 예시 코드를 참고하자면 제 함수의 경우 foo(s, r, i, j)foo(r, s, i, j)는 같은 값을 반환하였습니다.

 

이런 경우 중복되는 연산은 제거하고 다만 중복되는 데이터는 필요한 경우 같은 값을 복제한 후 이어붙이면 됩니다.

# 중복 연산 제거
all_lst = []

num = 0
for s in lst1:
    for r in lst1[num:len(lst1)]:
        for i in lst2:
            for j in lst2:
                example = foo(s, r, i, j)
                all_lst.append(example)
    num += 1

 

위의 코드는 한 번에 이해하기 조금 어려운 코드입니다. s와 r변수가 같은 리스트에서 추출되는 것에 집중해주세요.

 

예를 들어 list1에 ('A', 'B', 'C')가 저장되어 있는 경우 s와 r은 ('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')와 같이 추출됩니다.

 

이전에는 ('A', 'B'), ('B', 'A')와 같이 중복되는 쌍도 추출되었죠. 이런 매커니즘이라는 것만 알아주세요.

 

 

벡터 연산


반복문을 통한 연산을 벡터 연산으로 바꾸어 실행 속도를 개선할 수 있습니다.

 

벡터 연산이란 예를 들면 (1, 2, 3, 4, 5) 로 되어있는 배열을 2로 나누어 (0.5, 1, 1.5, 2, 2.5)와 같은 반환값을 한번에 구하는 방법을 말합니다.

 

위의 방법이 for문을 통해 배열에서 하나하나 값을 꺼내서 2로 나누는 방법보다 빠릅니다. (특히 데이터 양이 많아질수록)

 

제가 알기로는 for문을 통해 연산을 하면 CPU가 한 번에 하나의 연산을 처리하지만 벡터 연산의 경우는 CPU가 연산을 병렬적으로 처리하기 때문으로 알고 있습니다.

 

 

병렬 처리


우리가 직접 프로그램이 병렬적으로 연산을 하도록 지정을 해 줄 수도 있습니다.

 

하나의 프로그램 안에 여러 개의 쓰레드를 생성하고 각각의 쓰레드 안에 지정된 업무를 할당해주면 됩니다.

 

쉽게 말하면 한 번에 여러개의 프로그램을 돌리는 것과 같습니다.

 

저의 경우는 33개 연도에 대해 변수를 구하는 작업을 수행하였는데 각각의 11개의 쓰레드에 3개 연도씩의 작업을 할당해준 후 프로그램을 실행하였습니다.

 

위의 경우 각기 다른 11개의 프로그램을 동시에 돌린 것과 같은 효과가 나타납니다.

(저의 경우 실행 속도가 11배 개선되지는 않았고 약 6.53배 향상되었습니다. 업무가 한번에 과중됨으로써 리소스를 많이 잡아먹기 때문으로 보입니다.)

 

쓰레드 개수는 본인 컴퓨터의 CPU의 코어의 개수, 혹은 거기에서 1을 제한만큼 할당해주는 것이 좋습니다.

 

하나의 코어에서 여러 개의 프로세스를 처리할 수도 있지만 이렇게 해야 CPU의 최대 효율로 동작할 수 있습니다.

 

저의 경우 CPU 코어 개수가 12개여서 쓰레드 개수를 11개로 설정하였습니다.

 

 


 

오늘은 제 경험에 기반하여 실행속도를 개선하는 몇 가지 방법에 대해 소개해보았습니다.