개발/Linux

 

 

  요약

 

다수의 스레드를 사용한 C/C++ 프로그램에서 clock() 함수를 이용했을 때 발생하는 문제점과 clock_gettime() 함수를 이용하여 수행 시간을 정확하게 측정할 수 있는 방법을 설명한다.

 

 

  clock() 함수를 이용한 시간 측정 방법과 그 문제점

 

일반적으로 C/C++ 프로그래밍 시, <time.h>에 포함된 clock() 함수를 이용하여 아래와 같은 방식으로 수행 시간을 측정한다.

 

clock_t begin, end;

 

begin = clock(); 

 

/ *

 

수행 시간 측정을 원하는 작업

 

* /

 

end = clock();

 

cout << ((end - begin) / CLOCKS_PER_SEC) << endl;

 

이 방법은 싱글스레드 프로그램에서는 정상적으로 동작하나 멀티스레드 프로그램에서 사용할 경우, 시간 측정이 올바르게 되지 않는 것을 확인할 수 있다. 이는 clock() 함수가 단순히 프로세스에 의해 사용 된 클럭 수를 리턴해주기 때문에 하나의 스레드에서 위의 코드를 이용해 시간을 측정하는 동안 다른 스레드의 동작에 의해 클럭 값이 증가하게 되기 때문이다.


 


 

  clock_gettime() 함수를 이용한 올바른 시간 측정 방법

 

정확한 수행 시간을 측정하기 위해서는 <time.h>에 포함된 clock_gettime() 함수를 이용해야 한다. clock_gettime() 함수는 시간을 측정할 시계의 타입을 정의하는 clockid_ttimespec이라는 구조체를 인자로 갖는다.

  • clockid_t : 시계의 타입을 나타내는 인자로써, POSIX에서는 기본적으로 2가지 타입을 제공한다.

  • CLOCK_REALTIME

    시스템 전역에서 사용되는 실제 시간 (Epoch 기준)

    CLOCK_MONOTONIC

    특정 시점 이후로 흐른 시간 (ex. 부팅 후 시간)

  • timespec : 초와 나노초를 멤버로 갖는 구조체. <time.h>에 정의되어 있음.
struct timespec {
        time_t   tv_sec;        /* seconds */
        long     tv_nsec;       /* nanoseconds */
};

 

clock_gettime() 함수는 clockid_t에 입력한 시계를 이용하여 시간을 측정하므로 프로세스에서 사용한 클럭 수를 세는 clock() 함수보다 정확한 수행 시간 측정이 가능하다. 사용 방법은 다음과 같다. clockid_t의 인자로 CLOCK_MONOTONIC 대신 CLOCK_REALTIME을 사용해도 되지만 CLOCK_REALTIME 사용 시, 시간 측정 중에 시스템 시간이 변경될 경우 측정값이 변한다는 문제점이 있다.

 

struct timespec begin, end ;

 

clock_gettime(CLOCK_MONOTONIC, &begin);

 

/ *

 

수행 시간 측정을 원하는 작업

 

* /

 

clock_gettime(CLOCK_MONOTONIC, &end);

 

cout << (end.tv_sec - begin.tv_sec) + (end.tv_nsec - begin.tv_nsec) / 1000000000.0 << endl;

 

 

 

 

 

  요약

 

리눅스에서 홈 디렉토리 아래에 위치하는 8개의 사용자 폴더(Desktop, Documents, Downloads, Music, Pictures, Public, Templates, Videos)의 기본 경로를 변경하는 방법에 대해 설명한다.

 

 

  변경 방법

 

디렉토리의 경로는 user-dirs.dirs 라는 파일에 저장되어 있다. nano, gedit 등의 에디터를 통해 아래의 파일을 열어준다.

 

~/.config/user-dirs.dirs

 

파일을 열어보면 기본 설정은 아래와 같다. 여기서 빨간색으로 밑줄 친 부분을 원하는 경로로 바꿔준 뒤 재부팅 또는 재로그인을 해주면 경로가 변경된 것을 확인할 수 있다.

 

XDG_DESKTOP_DIR="$HOME/Desktop"
XDG_DOWNLOAD_DIR="$HOME/Downloads"
XDG_TEMPLATES_DIR="$HOME/Templates"
XDG_PUBLICSHARE_DIR="$HOME/Public"
XDG_DOCUMENTS_DIR="$HOME/Documents"
XDG_MUSIC_DIR="$HOME/Music"
XDG_PICTURES_DIR="$HOME/Pictures" 
XDG_VIDEOS_DIR="$HOME/Videos"


 


 

  예시

 

user-dirs.dirs 파일을 열어 문서 디렉토리를 '~/Desktop/문서'로 변경한 결과이다.

 

 

기본 문서 폴더의 경로가 '~/Documents'에서 '~/Desktop/문서'로 변경된 것을 확인할 수 있다.

 

 

 



  설명


리눅스에서는 'grep' 명령어를 통해 원하는 문자열 패턴을 포함하는 행들을 출력할 수 있다.

입력 파일이 있을 경우 입력 파일 내에서, 없는 경우 표준 입력 내에서 지정한 패턴을 검색하여 일치하는 행을 출력한다.



  사용법


기본적인 사용법은 아래와 같다.


grep [OPTIONS] PATTERN [FILE]


'grep' 명령어는 단독으로 사용되기도 하지만 'find' 같은 출력 명령어와 함께 사용하여 원하는 결과를 필터링하는 데에도 자주 사용된다.


출력명령어 | grep PATTERN


'grep' 명령어에서 사용할 수 있는 옵션은 다음과 같다.


 옵션

설명 

 -c

 패턴을 포함하는 행을 출력하는 대신, 일치하는 행의 수를 출력

 -L

 패턴을 포함하지 않는 파일의 이름을 출력

 -l

 패턴을 포함하는 파일의 이름을 출력

 -m [NUM]

 파일당 일치하는 행을 최대 NUM 개까지만 출력

 -o

 일치하는 부분만 출력

 -q

 결과를 출력하지 않음

 -s

 잘못된 입력 파일에 대한 오류 표시하지 않음

 -i

 대소문자 구분하지 않음 

 -v

 패턴과 일치하지 않는 행만 출력

 -n

 행 번호를 함께 출력

 -w

 패턴과 같은 단어를 정확하게 포함하는 행만 출력

 -x

 패턴이 전체 행과 일치하는 행만 출력

-r

 서브 디렉토리의 파일까지 모두 검사

 -a

 바이너리 파일을 텍스트 파일처럼 인식하여 검사





  사용 예제


1. 현재 디렉토리에서 'server' 를 포함하는 파일을 찾아서 출력



2. 현재 디렉토리의 파일 중 'lecture' 라는 문자열을 포함하는 파일만 출력



3. 현재 디렉토리의 모든 파일을 대상으로 'char' 라는 문자열을 포함하고 있는 행 출력



4. 3의 결과에 -w 옵션을 추가하여 정확하게 'char' 라는 단어를 포함하는 행만 출력







리눅스에서는 'df' 'du' 명령어를 이용해 디스크 용량을 확인할 수 있다.


df [OPTIONS] [FILE] : 시스템에 마운트 된 디스크의 남은 용량을 확인하는 명령어. 아래와 같은 옵션과 함께 사용 가능하다.


 옵션

 설명

 -a

 모든 파일 시스템을 출력

 -B [SIZE]

 지정 크기를 블록 단위로 하여 용량 표시

 -h

 용량을 가장 보기 편한 단위로 변환하여 보여줌 (ex. 1K, 256M, 4G)

 -H

 용량을 1024가 아닌 1000단위로 표시

 -i

 inode의 남은 공간, 사용 공간, 사용 퍼센트를 출력

 -k

 '-B 1K'와 같은 의미

 -l

 출력 목록을 로컬 파일 시스템으로 제한

 -P

 POSIX에서 사용되는 형태로 출력

 -t [TYPE]

 출력 목록을 파일 시스템의 타입(TYPE)으로 제한

 -T

 파일 시스템의 타입을 같이 출력 (ex. ext4)

 -x [TYPE]

 출력 목록에서 파일 시스템의 타입(TYPE)만 제외




du [OPTIONS] [FILE] : 파일의 디스크 사용량을 확인하는 명령어. 아래와 같은 옵션과 함께 사용 가능하다.


 옵션

 설명

 -a

 현재 디렉토리 아래의 모든 파일과 디렉토리의 사용 정보를 출력

 -B [SIZE]

 지정 크기를 블록 단위로 하여 용량 표시

 -b

 바이트 단위 출력

 -c

 출력된 의 사용량 합계 표시

 -D [FILE]

 입력한 심볼릭 링크 파일만 역참조(원본 파일의 용량을 출력)

 -h

 용량을 가장 보기 편한 단위로 변환하여 보여줌

 -H

 '-D' 옵션과 동일한 기능 수행

 -k

 '-B 1K' 옵션과 동일한 기능 수행

 -l

 하드 링크 파일일 경우, 여러번 용량을 카운트(원본과 하드 링크 파일 모두 카운트)

 -L

 모든 심볼릭 링크 파일들을 역참조

 -S

 서브디렉토리들은 결과에서 제외

 -s

 전체 사용량만을 출력

 -x

 다른 파일 시스템의 디렉토리는 결과에 포함하지 않음




 

리눅스에서 gcc, g++ 컴파일러를 이용하여 코드를 컴파일 시 다양한 최적화 옵션 사용이 가능하다.

 

 

$ g++ -(optimization options) test.cpp

 

 

각 옵션들은 매우 다양하기 때문에 일반적으로 이들을 묶어 간편하게 사용 가능한 '-O1', '-O2', '-O3' 옵션을 사용한다.

 

KLDP에서 설명하는 각 옵션의 최적화 방식은 다음과 같다.

 

 

'-O1'의 경우, 만들어지는 오브젝트, 또는 실행 파일을 가능한 작게 하면서, 컴파일 시간이 오래걸리지 않는 선에서 최적화를 수행.

'-O2'의 경우, 만들어지는 코드가 가능한 빠르게 수행되도록 하지만, 코드의 크기가 너무 커지지 않도록 하는 선에서 최적화를 수행.

'-O3'의 경우, 코드의 크기는 전혀 신경 쓰지 않고, 오직 빠른 코드를 만들어 내기 위해 최적화를 수행.

 


 

KLDP에서는 '-O2' 옵션과 '-O3' 옵션의 속도에 대해 아래와 같이 설명하는데, 직접 다양한 코드에 사용해 본 결과 속도는 '-O2'와 '-O3' 옵션이 비슷한 성능을 보인다.

 

 

'-O3'로 만들어낸 코드가 반드시 '-O2'를 써서 만들어낸 코드보다 빠르다는 보장은 없다는 것입니다.

왜냐하면, 보통 CPU가 기계어를 수행할 때, 일정한 분량만큼 먼저 CPU 내부의 cache(캐시)에 불러와서 수행하는데, '-O3'를 써서 만든 코드는 대개 크기가 커서, 이 cache에 들어갈 수 있는 명령의 양이 상대적으로 적어지기 때문에, 오히려 느려질 가능성도 있습니다.

 

 

하지만 최적화 옵션을 사용하고 안하고는 차이가 크니 컴파일시 꼭 사용하는 것을 추천한다.

 

 

 

+ Recent posts