1.
Low Latency Application을 개발하기 위해 Linux을 많이 쓴다고 이야기했습니다.
그렇지만 Linux 설치만으로 모든 문제를 해결할 수 없습니다. 어찌보면 Linux도입은 새로운? 도전이고 문제해결과정입니다. 쉽지 않습니다. 현재 경쟁은 초단위도 아니고 밀리초단위도 아닙니다. 마이크로초이거나 나노초단위입니다.
얼마전 ZeroM의 Throughput 결과를 올린 적이 있습니다. 이 때 CPU Affinity를 적용한 경우와? 하지 않은 경우는 커다란 – 물론 마이크로초를? 기준으로 할 때 – 차이를 보여줍니다. 다른 경우도 들었습니다. 29West라고 미국에서 유명한 제품이 있습니다.? InfiniBand환경에선 최고의 성능을 보여준다고 합니다. 자! 대형 벤더의 X.86서버를 도입하고 레드햇 리눅스서버를 설치하고 OpenFabric을 깔고 Infiniband카드를 설치하면 원하는 성능이 나올까요? 모 회의사에서 미국에 있는 개발자까지 데려와서 BMT를 해봤지만 원하는 성능을 낼 수 없었다고 합니다.Linux에서 튜닝할 부분이 워낙 많고 깊었기 때문입니다.
Topics in High-Performance Messaging
AIX와 Solaris는 Unix 계열의 OS이지만 다른 철학을 가진 듯 합니다. Solaris가 개발자에게 많은 권한을 준 OS라면 AIX는 OS스스로가 많은 역할을 합니다. 안정성과 유연성사이에서 선택을 하여야 합니다. 2000년초반 Sun Enterprise Server가 시장을 휩쓸 때 Solaris환경에서 트레이딩프로그램을 개발하는 경우가 많았습니다. 이 때 개발자들이 해야할 일중 하나가 System Tuning입니다. 네트워크, Shared Memory등등 트레이딩에 영향을 미치는 패러매터를 찾아서 적절한 값을 변경하여야 했습니다. 리눅스도 마찬가지입니다. Solaris에 비해 Linux는 아주 유연합니다. 소스가 공개되어 있기때문에 개발자가 원하는 입맛대로 변형이 가능합니다. 물론 안정성을 헤칠 수 있는 가능성은 높아집니다.
2.
지난 주 본격적인 통합시험을 위하여 DELL로부터 R610모델을 임대했습니다. 6Core의 Intel Xeon CPU를 1개 탑재한 서버입니다. OS는 CentOS 64Bit를 설치하였습니다. 외장형 DVD를 구하지 못해 난항을 겪었지만 주변의 도움을 받아서 무사히 설치하였습니다. 우선 ZeroM을 받아서 설치를 하려고 합니다. 현재 마무리작업중입니다. 이용자설명서와 설치파일을 주말에 받을 예정입니다.? 설치를 한 후 Kernel 변수등을 조정하면서 성능시험을 할 계획입니다.
비슷한 사례를 조사했습니다. 현재 RHEL Realtime버전을 구매하면 따라오는 메시징제품으로 Qpid가 있습니다. 이와 같이 AMQP를 지원하는 오픈소스 메시징제품중 OpenAMQ가 있습니다. ZeroMQ를 만든 회사가 개발한 제품이면서 AMQP를 처음으로 개발한 회사입니다. 이중에 튜닝과 관련된 글이 있습니다.
http://www.openamq.org/tutorial:tuning-openamq-for-low-latency
위의 내용을 보면 Linux를 리얼타임OS처럼 사용할 수 있도록 몇가지 작업을 하라고 권고합니다.
(*)Recompile your kernel with kernel preemption on (either CONFIG_PREEPT=y or
CONFIG_PREEMPT_VOLUNTARY=y and CONFIG_PREEMPT_BKL=y).
(*)Use such a scheduling policy that gives OpenAMQ priority over other processes (say use round-robin scheduling).
(*)Lock OpenAMQ into physical memory to avoid page faults.
(*)CPU affinities, CPU shielding etc.
이중에서 첫번째와 같이 커널을 Rebuild할 수는 없습니다. 금융기관에서 사용하는 리눅스라고 하더라도 판매처로부터 기술지원을 받아야 합니다. 그런데 커널을 재구축하면 유지보수를 받지 못하기때문입니다. 이중에서 CPU Affinity와 관련한 것은 시험을 해볼 수 있을 듯 합니다.
3.
CPU Affinity나 CPU Isolation이라는 말은 몇달 전 접했습니다. 어떤 제품의 소스를 보는데 Affinity라는 단어가 툭 튀어나오길래 열심히 찾아보았습니다. CPU Affinity란 다중 CPU를 가진 컴퓨터에서 각 Process에 대해 Process가 사용할(사용하지 않을) CPU를 명시하는 기능을 지정하는 기능을 말합니다.? 이론적으로 다음과 같은 장점이 있다고 합니다.
The first benefit of CPU affinity is optimizing cache performance.
A second benefit of CPU affinity is if multiple threads are accessing the same data, it can make sense to bind them all to the same processor.The third benefit is found in real-time or time-sensitive applications. In this approach, all the system processes are bound to a subset of the processors on the system. The application then is bound to the remaining processors. For example in a dual-processor system, the application would be bound to one processor, and all other processes are bound to the other. This ensures that the application receives the full attention of the processor.
CPU Affinity and taskset중에서
세번째 장점을 트레이딩 어플리케이션과 연결하여 보도록 하겠습니다.? 트레이딩 어플리케이션은 시세처리부(Feed Handler), 주문생성부(Strategy Manager), 주문전송(Order Gateway)로 구성되어 있습니다. 소프트웨어 구성을 각 독립된 프로세스로 구성하고 각 프로세스는 IPC통신을 한다고 하고 서버는 6 Core CPU가 2개 있다고 합시다.
일반적인 방법은 각각 프로세스를 개발합니다. Multi Thread 혹은 Multi Process로 개발합니다. 다음으로 Init.d에 등록하면 OS가 프로세스를 시작하고 각각 Core를 할당합니다. 만약 Core의 자원이 부족하면 다른 Core의 자원을 이용하도록 스케듈링(Scheduling)합니다. 멀티코어환경에 맞도록 소프트웨어를 수정하지 않았다고 하면 90년대말부터 사용했던 구조가 그대로 이용됩니다.
CPU Affinity를 적용하면 어떻게 될까요 우선 CPU중 하나는 OS와 관련된 프로세스가 사용하도록 합니다. 나머지 CPU=6 Core를 트레이딩 어플리케이션이 사용하도록 지정합니다. FH중 현물은 CPU7, 파생은 CPU8, 주문생성은 CPU9, 주문전송은 CPU10으로 합니다.
Latency에서 차이가 있을까요,없을까요 물론 통합시험을 하여야 하지만 현재까지 시험결과를 놓고 보면 차이가 있습니다. 또한 IPC Messaging이 지향하는 트레이딩 어플리케이션 구조이기도 합니다.
4.
그러면 CPU Affinity를 어떻게 하여야 할까요 우선 Linux를 기준으로 설명하도록 하겠습니다. 기분적으로 Command를 이용하면 간단히 CPU Affinity를 할 수 있습니다. 명령어는 taskset입니다.
1 2 3 4 5 6 7 |
# bind a task to cpu 4 (remember this is a cpu mask) taskset 8 /usr/local/bin/my_embedded_process # or for an already running process id (PID) to cpu0 and cpu 1 taskset -p 0 PID#1 taskset -p 1 PID#2 etc |
taskset으로 하는 방법이 시험단계에서 적합한 방법이라고 하면, 운용단계는 isolcpus라는 커널변수를 사용하는 것이 좋습니다.Redhat Realtime을 Affinity Howto를 보시면 잘 설명되어 있습니다. 물론 sched_setaffinity() 와 같은 함수를 사용하여 개발단계에서 적용할 수 있습니다. 현재 개발된 ZeroFeeder나 ZeroM은 CPU Affinity를 지정할 수 있는 환경설정기능을 제공하고 있습니다.
Howto RHEL-RT – Affinity Howto
Linux Setting processor affinity for a certain task or process
Isolcpus
그러면 Solaris나 AIX는 어떨까요? 성능이 어떨지 모르지만 CPU Affinity기능을 제공합니다. 먼저 Solaris의 경우 pbind와 psrset를 사용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//pbind 이용하기 //특징: non-exclusive, processor에 프로세스를 바인딩함. # pbind -b processor_id pid /* cpu에 프로세스 바인딩 */ # pbind -u pid /* 프로세스 언바인딩 */ # pbind -q pid /* 프로세스 바인딩정보 확인하기 */ //psrset 이용하기 //특징: exclusive, processor set에 프로세스를 바인딩함. # psrset -c [processor_id ...] /* processor set 생성 */ # psrset -a processor_set_id processor_id ... /* processor set에 cpu 추가하기 */ # psrset -r processor_id ... /* processor set에서 cpu 빼내기 */ # psrset -d processor_set_id /* processor set 삭제 */ # psrset -e processor_set_id command [argument(s)...] /* 명령어를 특정 processor set에 바인딩해서 실행 */ # psrset -p [processorid ...] /* cpu가 어느 processor set에 속해있는지 확인 */ # psrset -b processor_set_id pid ... /* 프로세스를 processor set에 바인딩 하기 */ # psrset -u pid ... /* 프로세스 언바인딩하기 */ # psrset -q [pid ...] /* 프로세스가 어느 processor set에 바인딩 되었는지 확인 */ # psrset [-i] [processor_set_id ...] /* processor set에 할당된 cpu 정보 확인 */ // processor set에 바인딩 된 프로세스 확인하기 # prstat -C psrsetlist |
만약 하나의 서버내에서 서로 다른 영역으로 구분하여 서비스를 하고자 할 경우엔 Solaris Container Technology를 이용한 방법이 있습니다.
Solaris Zones: Resource Controls – CPU
만약 개발자라고 하면 다음과 같은 함수를 이용하실 수 있습니다.
In some instances you can get better performance, or reproducibility, by?restricting the processors that a thread runs on. Linux has pthread_set_affinity_np (the ‘np’ tag means non-portable). On Solaris?you have a number of nearly equivalent options:
* Processor sets where you create a set of processors and allow only particular processes to run on this set.
* Processor_bind, where you bind a particular process or thread to a particular virtual CPU. The thread cannot migrate off this CPU, but?other threads can run on it. This means that you need to coordinate?between different processes to ensure that they are not all allocated to?the same CPU.
* Locality groups. On a NUMA system, a locality?group is a set of CPUs which share the same memory local memory.?Processes that remain executing on processors within their locality
group will continue to get low memory access times, if they get?scheduled to processors outside the group their memory access times may?increase.
Setting thread/process affinity중에서
혹시 Linux와의 차이를 알고 싶으면 아래 글을 참고로 하시길 바랍니다.
Comparison of Solaris OS and Linux for Application Developers
마지막으로 AIX에서 Affinity를 적용하려면 아래 자료를 참조하시길 바랍니다.
Processor affinity on AIX
CPU Affinity가 모든 어플리케이션에서 유용한 기능을 아닐 듯 합니다. 어플리케이션의 특징에 따라 선택적으로 적용하여야 합니다. 그렇기 위해선 다양한 시험이 필요할 듯 합니다.
5.
마지막으로 Linux와 관련된 자료를 정리하면서 든 생각은 Low Latency를 위해서는 Linux Kernel에 대한 학습을 하여야 겠다는 생각이 들었습니다. 몇가지 자료를 찾아서 구매하였지만 우선 RedHat제품중 Realtime용으로 판매하는 MRG 튜닝가이드가 도움이 되었습니다.
다음으로 ‘Understanding Linux Kernel 3rd Edition’이 있습니다. 구글에서 2nd Edition은 PDF로 찾을 수 있습니다. 확인해보시길 바랍니다.
마지막으로 ‘Linux Kernel in a Nutshell’이라는 책은 전문을 보실 수 있습니다.
참고로 다양한 종류의 Unix별로 Process 및 Memory를 사용하기 위한 API가 어떤 것이 있는지를 정리한 자료입니다. Windows부터 Linux까지 거의 대부분을 정리한 자료입니다.