본문 바로가기

Library

메모리 풀 형식의 할당기 제작 (Prototype) 한달 전부터 고심을 거듭하던 메모리 풀 형식의 할당기 만드는 것을 대충 끝냈다. 생각보다 골치 아픈 일이었다. 단순히 커다란 힙을 할당 받고, 그 크기에 따라 적절한 할당 개체를 불러 할당 / 해제 함수를 부르면 될거라고 생각했는데, 성능에 민감한 부분이 많았다. 즉, 스택 상에서 하부 구조끼리 단순히 복사가 가능한 부분과, 반드시 힙에 생성해야 하는 부분을 파악해야 했다. 또, std::vector가 최대의 성능을 내는 것이 컨테이너의 끝에서 원소의 추가 / 삭제가 일어날 때라는 것도 고려해야 했다. 기본적인 컨셉은 Loki의 SmallObj에서 가져왔는데, SmallObj의 가장 하부 구조인 Chunk를 거의 그대로 차용했다. 그리고 가변 사이즈의 메모리 풀을 지원하기 위해 Loki::SmallObj.. 더보기
False Position Method(Linear Interpolation Method) BiSection Method는 간단하게 구현할 수 있는 탐색 기법이지만, 처음에 설정된 구간이 적절하지 않은 경우 불필요한 계산이 많아진다는 단점이 있다. 이에 비해 False Position Method(Linear Interpolation)은 훨씬 효율적인 근을 구하는 방법이다. False Position Method는 탐색하고자 하는 구간 [a, b]에서 f(a)와 f(b)를 연결하는 직선이 y = 0과 만나는 지점에서부터 탐색을 시작한다. 다음에 선택되는 구간은 f(a)와 f(b)를 연결하는 직선이 y = 0과 만나는 교점 c에서의 함수값 f(c)와 f(b)를 연결하는 직선과, y = 0과의 교점이다. 즉, BiSection Method가 주어진 구간에서 중간점을 구하는 방식으로 근을 탐색하는 .. 더보기
BiSection Method BiSection Method는, 어떤 함수 f(x) = 0이 주어졌을 때, x를 찾기 위한 방법으로 특정 구간을 계속 반으로 나누어가면서 근의 존재 여부를 판단하는 방법이다. 여기서 f(x)는 연속 함수여야 한다. 여기서 구하고자 하는 x는 실근이므로, y = 0과 교점을 가져야 한다. 먼저, 특정 구간 [a, b]를 선택하여 f(a), f(b)를 계산하고, 중간점 (f(a) + f(b)) / 2를 계산한다. f(a) * f(mid)가 0보다 작다면, 다음에 탐색해야 할 구간은 [a, mid]가 되며, 반대로 0보다 크다면 다음에 탐색해야 하는 구간은 [mid, b]가 된다. Binary Search와 동일한 방법이라 할 수 있다. BiSection Method는 언제나 근을 찾을 수 있다는 것을 보장.. 더보기
Introduction to File Structure File Structure는, Data Structure와 비슷하면서도 다른 성격을 가지고 있다. 이것은 해당 작업이 주로 이루어지는 매체와 관련된 측면이 크다. 즉, Data Structure는 기본적으로 처리하고자 하는 모든 자료들이 메인 메모리에 올라가 있다는 것을 전제로 하며, 가능하다면 처리할 자료를 디스크로부터 한번에 읽어들여 메모리에 올려서 처리한다. 그렇지만, 사용자의 데이터를 모두 저장하기에는 아직까지 메모리의 가격은 비싸기 때문에, 컴퓨터에 저장되는 데이터를 메인 메모리에 모두 올려서 사용할 수 없다. 사용자는 메모리의 저장 용량을 보완하기 위해 어쩔 수 없이 보조 기억 장치를 선택하게 되며, 보통 마그네틱 하드 디스크를 선택하게 된다. 마그네틱 하드 디스크는 메인 메모리보다 훨씬 더 .. 더보기
Truncation Error and Round-Off Error 로그 함수나 사인 함수와 같은 것을 계산한다고 해보자. 가장 간단한 방법은, 간단히 계산기를 꺼내서 두들겨 보는 것이다. 그러나, 이것은 트랜지스터 시대를 살아가는 사람들의 이야기이고, 트랜지스터가 등장하기 전, 사람의 손으로만 계산을 해야 했던 시대에서는 어떠한가? 주어진 식을 테일러 급수와 같은 것으로 전개하여, 가능한 높은 정확도로 미리 계산하여 표로 만들어 두고, 이렇게 미리 만들어진 표를 참조하여 값을 얻는 것이 가장 간단한 방법이었을 것이다. 그러나, 이렇게 컴퓨터를 사용하는 방법이나, 급수 전개를 통한 방법으로 얻어진 값은 완전히 정확한 값은 아니다. 주어진 최초의 식을 테일러 급수를 사용하여 전개하면, 이것은 원래 식과 완전히 같은 식이 아니라, 비슷한 값을 얻을 수 있는 근사식의 형태로 .. 더보기
STL 벡터 내에서의 원소 정렬 std::vector에 어떤 원소들이 저장되어 있을 경우, T가 기본형이 아니라면 std::sort()와 같은 함수를 사용하기 위해서는 비교 함수를 제공해야 한다. std::sort()를 사용하는 예제는 대부분 기본형을 사용하기 때문에, 실질적으로 컨테이너 안의 원소들을 정렬하고 싶은 경우 난감했던 경우가 있을 것이다. std::vector의 원소의 정렬을 위한 비교 함수는, 가장 간단하게 다음과 같이 작성할 수 있다. bool Compare(T& lhs, T& rhs) { return lhs < rhs; // 비교하고 싶은 T 타입의 데이터 멤버를 비교해야 한다 } 이 방법은 비교 함수가 전역으로 선언되어야 하기 때문에 경우에 따라서는 적절하지 않을 수도 있다. 그리고, std::ve.. 더보기
메모리 풀 형식의 할당기 제작 C++에서 기본으로 제공하는 힙 할당자인 new와 delete는 그 성능이 시원치 않다. 일반적인 경우, 운영체제에서 힙에 대해서 메모리 풀을 구현하고 있기 때문에 일정 크기 이하에 대해서는 크게 체감할 수 있는 부분은 아니지만, 이렇게 제공되는 메모리 풀은 일반적인 목적에 맞춰 제작된 풀이므로, 그렇게 성능이 처지는 것도, 그렇게 성능이 좋은 것도 아니다. 물론, 이것은 new와 delete 자체가 조악하다는 것이 아니라, 만들고자 하는 프로그램에서 요청되는 메모리 할당 / 해제 유형에 new와 delete가 잘 맞지 않을 수도 있다는 뜻이다. 따라서, 프로그램의 메모리 요청 유형에 적합한 할당기를 만들 필요성이 있는데.. 할당은 어떻게 하더라도 사실 그렇게까지 차이가 나지 않는 것 같은데, 문제는 메.. 더보기
유효한 뮤텍스의 범위 설정 POSIX PTHREAD나 Win32 Thread의 경우, 프로세스 내에서 스레드의 동기화를 제공하는 방법으로 pthread는 뮤텍스의 속성을 지정하게 되고, Win32에서는 이런 경우에 특화되어 있는 경량형 뮤텍스인 CRITICAL_SECTION 구조체를 사용하게 된다. 만약 프로세스 사이에서 스레드의 동기화가 필요하다면 pthread는 뮤텍스의 속성을 지정하는 pthread_mutexattr_t을 적절하게 설정하고, Win32의 경우에는 핸들을 사용하는 뮤텍스를 생성하여 사용한다. (즉, 커널 오브젝트를 생성한다) 여튼, 뮤텍스를 사용하고자 마음 먹었다면, 중요한 것은 생성한 뮤텍스의 범위를 어떻게 설정하는가이다. 즉, 여러개의 스레드가 존재하고, 이 스레드들이 공유된 메모리 영역에 접근하고자 할 때.. 더보기
POSIX PTHREAD for Win32 Win32 환경에서 스레드 프로그래밍을 한다면, 당연히 Win32 스레드를 사용할 것이다. 스레드와 동기화 매커니즘은, 그 플랫폼에서 제공하는 관련 라이브러리를 사용하는 것이 가장 성능이 좋고, 안정성도 뛰어나기 때문이다. 다만, 문제는 Win32 스레드는 특정 벤더의, 특정 플랫폼에서의 구현이라는 점이다. Win32 스레드도 사용하기 쉬운 편에 속하지만, 윈도우를 어느 정도 알고 있어야 한다. 간단히 말해, 널리 알려진 POSIX PTHREAD와 다르기 때문에, Win32 환경에서 스레드 프로그래밍을 시작하려는 사람에게는 적당하지 않다. 특히, GNU 환경을 Win32에 포팅한 MinGW에서 스레드 관련 라이브러리를 제공하지 않기 때문에, 이런 아쉬움은 더욱 크다. 이런 사람들을 위해 POSIX PTH.. 더보기
코드는 작성하면 반드시 시간을 두고 다시 생각해보도록 라이브러리 코드를 작성하는 것은 매우 신중해야 한다. 라이브러리 코드는 클라이언트 코드와는 다르게, 한번 사용되기 시작하면 그것에 의존하는 코드들이 만들어지기 때문에, 나중에 이 인터페이스를 변경하는 것은 간단한 문제가 아니다. 상대적으로 클라이언트 코드는 크게 신경쓰지 않고 작성해도 별 문제가 없지만, 라이브러리 코드는, 바로 클라이언트를 작성하는데 사용하지 말고 시간을 두고 여러번 사용하면서, 충분히 코드를 검토하기 바란다. 이것은 어떻게 보면 글쓰기의 퇴고와 비슷하다고 할 수 있다. 시간을 두고 다시 생각해보면, 그 당시에는 보이지 않던 문제가 새롭게 보일 수 있고, 완벽하다고 생각했던 디자인에 중복이 존재하거나, 불필요한 요소를 포함하고 있는 경우도 있다. 프로그래머란 족속들이 워낙 단기간에 많은.. 더보기