intel TBB를 써서 메모리 할당하기

월 초에 포스팅한 내용이지만, 약간 내용을 추가해보는 의미로 글 하나 남기기.

intel TBB 2.2 부터는 Windows 환경이나 linux 환경에서 intel TBB를 써서 기본 할당자(malloc/free, 그리고 new/delete)를 덮어 쓸 수 있게 되었다. 그래서 어떻게 하는지 + 약간의 성능 비교를 해봤다.

프로그래머가 직접 malloc/free 혹은 new/delete를 덮어 쓰는 좀 안 이쁜 방법말고, hoard allocator 같은 방법을 제공할 것 같아서 새로 추가된 헤더들을 뒤져보니 이런 코드가 있다.1

그냥 link 시점에 malloc/free 부분을 해당 lib의 그것으로 치환하고 실제 실행 시점에 호출되게 바꾸는 형태 (debugger를 붙여보니 tbbmalloc_proxy.dll 을 통해서 동작하는걸 확인할 수 있었다)

tbb/tbbmalloc_proxy.h (GNU GPL v2)

Replacing the standard memory allocation routines in Microsoft* C/C++ RTL
(malloc/free, global new/delete, etc.) with the TBB memory allocator.

Include the following header to a source of any binary which is loaded during
application startup

#include "tbb/tbbmalloc_proxy.h"

or add following parameters to the linker options for the binary which is
loaded during application startup. It can be either exe-file or dll.

For win32
tbbmalloc_proxy.lib /INCLUDE:"___TBB_malloc_proxy"
win64
tbbmalloc_proxy.lib /INCLUDE:"__TBB_malloc_proxy"

이 헤더를 include 하고나서 다음과 같이 간단한 — 10bytes~41 bytes 정도의 메모리를 10만 번 할당하고 해제하는걸 반복하는 – 코드를 짜서 내 데스크탑에 코어 수(=2)에 맞게 띄워서 돌려봤다.

const int N = 100000;
const int M = 1000;
unsigned _stdcall testProc(void* arg) {
	vector<BYTE*> allocs;
	allocs.reserve(N);
	for (int j = 0; j < M; ++j) {
		for (int i = 0; i < N; ++i)
			allocs.push_back(new BYTE[10 + rand() & 31]);
		for(int i = 0; i < N; ++i)
			delete [] allocs[i];
		allocs.clear();
	}
	return 0;
}

#include “tbbmalloc_proxy.h” 한 것과 안 한 것이 각각 7.10s, 16.5s 정도의 시간이 걸렸다. 2 배가 넘는 수행 시간 차이.

물론 이 정도로 무작정 메모리를 할당하고/해제하지는 않겠지만, 작은 양의 메모리(크면 차이가 좀 더 줄어들 수 있다)를 반복해서 복수의 스레드가 경쟁적으로 할당/해제할 경우, 멀티스레드에 최적화되지 않은 CRT의 malloc/free는 성능이 심히 떨어질 수 있다. 반면에 scalable_alloc / free의 형태로 구현된 intel TBB는 멀티스레드 최적화를 우선시했기에 두 스레드가 경쟁해도 좋은 성능을 보여준다.

  • intel TBB 라이센스를 확인해봤는데, runtime에 dynamic-link만 하는 경우에는 GPL v2.에 대해서도 예외를 적용한다고 한다(물론 TBB만의 얘기다). 그래서 commercial support 없이 클라이언트 코드에서 dynamic-link해서 쓰는 경우에는(.so나 .dll 등) 라이센스를 구입하지 않고도 써도 되는 듯 하다.2 그래서인지 EPIC의 Unreal 3 엔진에 intel TBB가 통합되어 배포되기 시작했다.

  1. win32 용을 집에서 쓰는 데스크탑에 받아서 설치한거라 Win32 용 표현(?)만 있음에 주의. ↩︎

  2. 물론 GPL이 적용되도 서버는 배포할 일이 없으니 그냥 쓰면 되지만. ↩︎