본문 바로가기
iOS

어플은 몇개의 CPU 코어에서 실행되나요?

by 지금갑시다 2023. 9. 25.

 Swift 언어 베이스로 만든 어플리케이션이 실제 아이폰과 같은 디바이스에서 실행될때, CPU의 단일 코어에서 실행이 될까 아니면 여러 코어에서 병렬적으로 실행이 될까?

 

 고수준으로 발달한 HW, SW를 모두 개발하는 애플과 같은 회사들은 양쪽의 최적화가 굉장히 잘 되어 있겠죠? 하지만, 그 모든 코드와 로직들을 오픈소스로 공개하지는 않으니, Swift의 코드레벨Apple Document를 기반으로 위와 같은 질문에 대한 답을 추론해보도록 하겠습니다

 

 먼저 앱을 손가락으로 눌러 실행시키게 되면, 코드 덩어리였던 어플리케이션이 메인메모리에 올라오게 되면서 하나의 프로세스로 실행되게 됩니다. 이 프로세스 즉 어플리케이션은 실행과 동시에 한개의 프로세스로 실행되고 ios의 스케쥴링 정책에 따라 어느 CPU 코어에서 실행될지 결정됩니다. 프로세스는 처음 선택된 코어에서 계속 실행될 수도, 혹은 정책에 따라 다른 코어로 이동되어 연산되며 실행될 수도 있습니다.

 

 일반적으로 대부분의 iOS와 같은 OS들은 하나의 프로세스가 가지고 있는 여러 쓰레드들을 병렬적으로 CPU의 코어에서 실행시킬 수 있도록 설계되었기에 감히 예상해본다면, 하나의 프로세스가 된 어플은 여러 코어에서 병렬적으로 실행될 수 있을 것입니다.

 

 

 이를 Swift 코드로 확인해볼까요?

iOS 17 버전, iPhone 15 Pro 시뮬레이터에서 실행한 결과입니다.
print("ProcessorCount: \(ProcessInfo().processorCount)") // 8 출력
print("ActiveProcessorCount: \(ProcessInfo().activeProcessorCount)") // 8 출력

 ProcessInfo()는 현재 돌아가고 있는 프로세스에 대한 정보를 가지고 있고, 프로세서( == 코어)의 갯수와 함께 active되어 있는 프로세서의 갯수도 알 수 있습니다. 위의 코드만 본다면, 프로세스 레벨에서 하드웨어인 CPU의 코어 갯수를 셀 수 있으니, 프로세스가 돌아가면서 active되는 코어의 갯수가 달라질 수 있구나!

-> 즉 어플의 실행이 코어의 활용 갯수에 영향을 미칠 수 있겠구나! 생각해볼 수 있을 것입니다.

 

 

 하지만, 위의 코드 두줄만 보면 이해하기 어려운 부분이 생기죠.. 그래서 어떻게 어플이 실행되며 여러 코어를 점유하고 바뀌고 그런다는건데..??

 

 사실 이에 대한 답은 '프로세스의 코어 점유 갯수 변경' 과 같은 일들은 Swift 레벨에서 직접 처리하고 있지 않기 때문에 알기 어렵다 라는 겁니다. Swift로 만든 어플은, 아니 더 나아가서 다른 모든 언어들은 직접 CPU 레벨까지 생각하지 않고

 

내가 작성한 코드들을 HW로 보내고

HW에서는 전기신호로 어찌저찌~~~ 여기 저기 코어 왔다 갔다~~~~

잘 작동되어 코드에 대한 반응을 받는다!

 

까지만...! 책임이 있거든요ㅎ

 

 무슨 말이냐면 '전기신호로 어찌저찌~~~ 여기 저기 코어 왔다 갔다~~' 에 대한 부분은 Swift와 언어를 사용하여 개발을 하는 사람들이 고려하지 않아도 된다는 점입니다. 이는 SW개발자의 영역이 아닌, HW와 시스템SW 개발자들의 영역이죠. 개발자들이 굳이 반도체가 어떻게 작동하지 몰라도 코딩을 할 수 있는 것도 동일하게 추상화된 레벨에서 타자를 치는 코딩만 하면 되는 것이기 때문입니다.


프로세스 코어 연관 찾아보기

그러면 간접적으로나마 프로세스와 코어의 연관관계를 Swift 레포지토리에서 찾아봅시다ㅎ

출처: https://github.com/apple/swift/blob/2f7b42ceaf539ee85bf139fab5d269a8bc415401/utils/build-tooling-libs#L356%EF%BB%BF

 

 swift 레포를 보면, swift 빌드를 할때, C++ 라이브러리인 multiprocessing의 cpu_count() 함수를 활용해 사용 가능한 cpu의 갯수를 확인하는 것을 알 수 있습니다. 

 

 이와 유사하게

coverage-touch-tests를 할 때, multiprocessing 모듈에서 cpu_count()를 활용해 NUM_CORES 즉 코어의 갯수를 정의합니다.

 

multoprocessing 모듈에서 cpu_count()를 활용한다는 것은 process가 멀티가 될때, 즉 한개 말고 여러개의 프로세스가 돌아갈때 cpu_count()가 영향을 받을 수 있다는 의미이겠죠?

 

그렇다면, 단일 프로세스 즉 단일 어플에서 여러 프로세스를 만들 수 있다면, 우리는 해당 어플이 여러 코어에서 돌아갈 수 있는 환경이 될 수 있겠구나! 라고 생각을 할 수 있게 됩니다.

 

그렇다면, 이제 어플에서 프로세스를 만들 수만 있으면 그건 멀티 코어에서 돌아갈 수 있는 어플이다! 라고 말할 수 있게 되는거죠!


여러 프로세스 만들기

자!! 다 끝났습니다. 우리.. 예전에 배웠던 시스템 프로그래밍, 운영체제를 생각해보며.. fork() 시스템 콜을 떠올려 봅시다.

바로 현재 진행되고 있는 프로세스에서 동일하게 자식 프로세스를 만들면 되는 것이죠.

fork() 콜을 통해 자식 프로세스가 만들어지면 부모와 자식 프로세스가 진행중인 것이니, 멀티코어에서 실행될 수 있는 환경이 구비된 것입니다.

 

가보자고!

BUT!! fork() 콜을 하려했더니..!

출처: https://github.com/apple/swift/blob/2f7b42ceaf539ee85bf139fab5d269a8bc415401/stdlib/public/Platform/Platform.swift#L320

 

Please use threads or posix_spawn*() 이라고 하네요..! 우린 쓰레드를 만들 생각이 아니니까, posix 콜을 사용해봅시다!

    init() {
        print("ProcessorCount: \(ProcessInfo().processorCount)")
        print("ActiveProcessorCount: \(ProcessInfo().activeProcessorCount)")
        makeNewProcess()
    }
    
    func makeNewProcess() {
        let commandPath = "/bin/ls"
        print("Parent process ID: \(getpid())")
        var pid = pid_t()

        // pid에 자식 프로세스 pid를 넣는 과정
        let status = posix_spawn(&pid, commandPath, nil, nil, nil, nil)
        
        // posix_spawn 성공
        if status == 0 {
            print("Child process ID: \(pid)")
            var childStatus: Int32 = 0
            waitpid(pid, &childStatus, 0)
            
        } else {
            perror("posix_spawn")
        }
    }

결과 프린트 화면

 

Parent process ID와 Child process ID가 다르게 출력되는 것을 볼 수 있고, 우리는 이제 하나의 어플이 여러 코어에서 실행 될 수 있는 기반을 만든 것입니다!!! 예쓰!!!!!!!!!


정리

정리하자면!

1. 프로세스와 코어의 연관관계를 찾으려 했지만, Swift 언어 단에서 직접적인 코어 컨트롤을 하지는 않음!

2. 그래도 그 흔적을 찾기위해 Apple swift 레포에서 multiprocessing모듈의 cpu_count()함수를 찾음!

3. 아! 프로세스와 cpu_count()와의 연관관계가 있겠구나!

4. 그럼 하나의 프로세스에서 다른 프로세스를 실행시킬 수 있으면, 멀티 코어에서 동작이 가능하겠다!!

5. posix 시스템 콜로 프로세스 생성! -> 멀티 코어에서 동작이 될 수 있겠구나!

 

위와 같은 흐름으로 정리를 해보겠습니다ㅎ

 

+

 사실 위처럼 프로세스를 여러개 만들더라도, 멀티코어에서 앱이 돌아간다는 보장은 없습니다. 어찌되었든 Swift 언어에서의 흔적을 찾은 것 뿐이기 때문이죠.. 위와 같이 여러 프로세스를 만들어도 싱글코어에서 스케줄링되어 실행될 수도 있고, 프로세스를 만들지 않더라도 멀티 코어에서 실행될 수 있습니다! 항상 운영체제(OS)의 정책에 따라 실행되므로! 유념하시길 바랍니다!!

 

그럼 끘!! 

여기까지 읽으신 여러분 최고!!!!