본문 바로가기

Tech

[고급] 멀티 쓰레드에서 연속된 데이터 쉐어링 방법

연속된 데이터. 예를 들어 화상 이미지나 사운드 스트림 등등을 처리할 때 보통은 버퍼를 사용하고 버퍼 접근시 락을 걸 것이다.

 

락을 걸지 않고 시스템 딜레이 없이 고속 처리할 수 있는 방법을 간략히 소개한다.

 

먼저 버퍼는 256 크기의 데이터 구조이다.

이 때의 데이터 구조는 메모리 블럭일 수도 변수일 수도 있다.

 

이 버퍼는 두가지 인덱스 값을 갖는다. set를 위한 posSet, get을 위한 posGet. 모두 바이트로 선언된다는 것이 촛점이다.

그리고 FIFO 구조이다.

 

Why Byte ? 버퍼크기가 256이므로. 인덱스를 증가시킬 때 모듈라 연산이 필요없기 때문에.

조금 더 고속이면서도 깔끔한 코드가 가능하게 해준다. 펌웨어 코드에서 분명 유용할 것이라 믿는다.

 

그리고 쓰레드에서 버퍼를 동시에 접근을 할 때 두 쓰레드의 버퍼 접근 속도가 너무 차이 나지 않도록 한다.

속도 차이가 난다면 버퍼 Empty를 체크해야 하는 귀찮음이 있다.

 

연속된 데이터를 쉐어링한다는 것은 한 쓰레드에서 처리후 다른 쓰레드로 넘긴다는 의미가 있다.

그러므로 일방향이므로 두 쓰레드는 각각 posSet, posGet 인덱스를 나눠서 유일하게 쓰게 된다.

 

선행 쓰레드에서 posSet을 증가시키며 버퍼를 쓰게 되면 후행 쓰레드에서 posGet을 증가시키며 가져오는 것이다.

버퍼 풀은 고민할 필요가 없다. 후행 쓰레드가 늦는다는 것이며 버리는 데이터가 생긴다는 의미이다.

버려야할 데이터가 없어야 한다면 후행 쓰레드의 성능을 개선시켜야 하므로 또 다른 문제이다.

 

오직 버퍼 Empty만 고려해야 하는데 Empty를 고려하지 않고 posGet으로 같은 데이터를 계속 가져와서 처리하는 것은

시스템 자원 낭비이고 성능 최적화가 안되었다는 의미이다.

 

그러므로 최적화된 시스템을 구현할 시 버퍼 Full 과 Empty가 없도록 두 쓰레드의 속도를 잘 설계해야 한다.

이것이 가능하면 lock을 걸지 않아도 중단없이 실행되는 쓰레드 구조가 되고

이론 상으로는 가장 빠른 멀티 쓰레드 데이터 공유 구조가 될 수 있다.

 

조금 더 응용해서 Index 변수를 하나만 유지할 수도 있다.

put은 index로 get은 index-1이나 index-2를 사용하는 것이다.

이 역시 버퍼 동시 접근을 막을 수 있다.

 

이 컨셉으로 정확한 시스템 구현은 각 상황에 맞게 코딩해야 하므로 Full, Empty 처리 정책에 대해 세세한 언급은 하지 않는다.

 

 

핵심 내용 : 쓰레드 동기화에서 락을 걸지 말고 논스톱 시스템을 구현하자.