지난 번 글에서는 간단하게 왜 fractal 그리는 작업에 GPU가 필요한지에 대해 간단히 이야기를 해봤습니다. 이번에는 그 fractal을 그리는데 사용되는 CUDA에 대해 설명을 해보도록 하겠습니다.


  CUDA(Compute Unified Device Architecture)는 C언어(정확히는 CUDA C)를 사용해서 GPU에서 알고리즘을 작성할 수 있는 GPGPU 기술입니다. 정확히는 오직 Nvidia GPU에서만 지원하는 기술이죠. AMD GPU나 기타 다른 GPU에서도 비슷한 역할을 하는 OpenCL(Nvidia GPU에서도 돌아갑니다)이라는 것도 있지만, 제가 알기로는 CUDA가 더 좋다고 알고 있습니다. 요즘엔 딥 러닝 때문에 기본적으로 연산을 위해 GPU를 쓰는 경우가 있는데, 대체적으로 딥 러닝 프레임워크가 CUDA를 지원해서 딥 러닝 할 때는 어쩔 수 없이 Nvidia GPU를 고를 수 밖에 없는 일이 발생하기도 했습니다.


  원래 GPU는 CPU와 다르기 때문에 기본적으로 CUDA를 이용해 병렬 프로그래밍을 짤 때에도 기존 프로그래밍과는 조금 다른 방식으로 프로그래밍을 해야 합니다. 무엇보다 RAM을 동시에 같이 쓰지 않기 때문에 CUDA에서는 컴퓨터(Host)와 GPU(Device) 사이의 메모리 복사를 통해 작업물과 결과물을 주고 받습니다. 그리고 Kernel이라는 GPU에서의 function을 짜고 이를 GPU에서 돌려서 연산을 수행합니다. 즉, 기본적인 알고리즘은 아래와 같이 이뤄지게 됩니다.


1. CPU에서 GPU로 데이터 전송(Host to Device 메모리 복사)

2. GPU에서 kernel을 통해 데이터 연산을 수행(kernel 연산)

3. 연산 결과물을 GPU에서 CPU로 데이터 전송(Device to Host 메모리 복사)


이 과정을 원래는 CUDA의 기본 지원 언어인 C/C++에서 짤 때 일일히 구현해야 하는데, 제가 fractal 그리는 프로그램을 짤 때는 PyCUDA를 사용했기 때문에 저 과정을 간단하게 작성할 수 있었습니다. 제 프로그램에서 CUDA 부분만 가져와보면 아래와 같습니다.


kernel 부분

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
26
27
28
29
30
31
32
__global__ void calcMandelbrot(bool *isJulia, double *c, double *matrix, int *result) {
    int idx_x = blockIdx.x * blockDim.x + threadIdx.x;
    int idx_y = blockIdx.y * blockDim.y + threadIdx.y;
    double a = matrix[0+ (float)idx_x * matrix[2];
    double b = matrix[1+ (float)idx_y * matrix[2];
 
    double an = a, bn = b;
    double aan = an * an, bbn = bn * bn;
 
    for (int i = 0; i < 400; i+=5) {
        // iteration 1
        if (isJulia[0]) { // Julia Set
            bn = 2 * an * bn + c[1];
            an = aan - bbn + c[0];
            aan = an * an;
            bbn = bn * bn;
        } else { // Mandelbrot Set
            bn = 2 * an * bn + b;
            an = aan - bbn + a;
            aan = an * an;
            bbn = bn * bn;
        }
 
        if (an * an + bn * bn > 4.0f) {
            result[idx_x * gridDim.y * blockDim.y + idx_y] = i;
            break;
        }
 
        ... 생략 ...
 
    }
}
cs


main 부분

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
26
27
28
29
def calcMandelbrot(type, start, size, unit, c=0 + 0j):
    """ Calculating and drawing mandelbrot set and julia set
    :param type: fractal type
    :param start: center point in plane
    :param size: image size(width, height)
    :param unit: gap among pixels
    :param c: julia constant
    :return: image 2D array (format: RGBA)
    """
 
    s = time()
 
    # change size to multiple of 16(bigger or equal to prior size). Because of threads per block is 16
    size = ((size + 255/ 256).astype(np.uint32) * 256
 
    result = np.empty((size[0], size[1]), np.int32)
 
    func = cu.get_function("calcMandelbrot")
    func(cuda.In(np.array([type == Fractal.JULIA], np.bool)),
         cuda.In(np.array([c.real, c.imag], np.float64)),
         cuda.In(np.array([start[0- size[0/ 2 * unit,
                           start[1- size[1/ 2 * unit, unit], np.float64)),
         cuda.Out(result),
         block=(16161), grid=(int(size[0/ 16), int(size[1/ 16)))
 
    # Because in image symmetric transformation occurs between x axis and y axis
    result = np.transpose(result)
 
    return array2imgarray(result, cc.m_cyclic_wrwbw_40_90_c42_s25)
cs


main부분을 보시면 16번째 줄에서 결과물을 복사해서 담을 CPU 메모리를 할당하고 있고, 18번째 줄에서 function을 가져와서 19번째 줄에서 호출을 합니다. 원래 C/C++ 같았으면 19번째 줄에서 파라미터 부분(cuda.In, cuda.Out)을 싸그리 할당하고 복사하는 복잡한 과정을 거쳐야 호출할 수 있는데, PyCUDA에서는 간단하게 GPU에 입력만 될 파라미터는 cuda.In으로, GPU에서 출력만 될 파라미터는 cuda.Out으로 처리만 하면 나머지 할당하고 복사하는 과정을 알아서 해줍니다. 만약에 GPU에 입력된 후 다시 출력될 파라미터 같은 경우는 cuda.InOut으로 해주면 간단하게 처리됩니다.


그런데 잘 보시면 func 호출 시 단순히 파라미터만 있는 것이 아니라 block이나 grid와 같은 것이 보입니다. 이것은 GPU에 얼마 만큼의 병렬 처리 단위를 생성해서 계산을 할 것인지를 정하는 것입니다. 제가 겪었던 첫번째 시행착오가 바로 이 부분이었죠.


CUDA에서 병렬 처리 단위는 block과 thread로 나눠집니다. 기본적으로 여러 개의 block이 있고, 이 block 안에 thread가 있는 것입니다. 그리고 각 thread는 연산을 할 때 자신의 위치를 지표로 삼아 데이터를 불러와서 연산을 합니다. 예를 들어 fractal 이미지 같은 경우 픽셀의 (x, y)값마다 thread가 있을테니 각 thread는 자신의 (x, y)에 대한 값을 연산합니다. CUDA에서는 이 (x, y)와 같은 thread index가 3차원까지 되어 있으며 각 차원 별로, 그리고 각 단위(block, thread) 별로 제한값이 있습니다. 이것은 GPU마다 다른데 특히 block 당 thread의 최대 개수는 최근 device 경우에는 1024개로 제한이 되어 있습니다. 이 제한 값은 Linux에서 CUDA 설치 시 제공되는 Sample 중 deviceQuery라는 것을 컴파일해서 실행해보면 알 수 있습니다. 제 경우(GTX 970)엔 아래와 같이 확인할 수 있습니다.


GTX 970 Device Query


이렇게 각 block과 thread 개수를 정해서 GPU에서 kernel을 실행하면 개수에 맞게 thread가 생성이 되어 kernel 함수가 연산을 수행합니다. 이때 자기 thread가 어디 위치에 있는 것인지 알아야 하기 때문에 CUDA에서는 기본적으로 gridDim, blockIdx, blockDim, threadIdx라는 상수를 제공합니다. 제가 이걸 프로그래밍하면서 당연하게 'blockIdx는 block의 위치값, blockDim은 block의 차원일테니, blockDim으로 block의 총 개수를 보면 되겠다!'라는 생각을 했었는데, 이게 아니더라고요. block의 총 개수: gridDim, thread의 총 개수: blockDim 입니다. blockIdx는 block의 index, threadIdx는 thread의 index이고요. 이 내용을 간단하게 그림으로 나타내면 아래와 같습니다. 3D는 그리기 귀찮아서, 2D로 그려봤습니다.


  암튼 이렇게 CUDA의 기본 구조를 파악하고 나서 간단하게 fractal 그리기 프로그램을 만들었습니다. 초기 버전은 단순하게 block 당 thread를 1개로만 해서 만들었습니다. 이때는 뭐 거의 800x800 그리는데 0.3초 정도로 매우 느렸습니다. 그래서 어떻게 해야 하나 싶어서 CUDA sample을 뒤져서 Mandelbrot 예제(옛날에 CUDA sample 뒤지다가 발견했었거든요 ㅇㅇ)를 찾아내서 코드를 비교해봤습니다. 전체적인 구조는 비슷하더라고요. 차이점을 찾아보니 일단 저는 단일 thread만 사용했고, 이상하게 CUDA sample은 loop를 일부 풀어놨습니다(다음 글에서 소개할 기술입니다). 아무래도 thread가 하나인 게 문제인 거 같아서 thread를 여러 개로 늘려봤더니, 속도가 100배 정도(...) 빨라졌습니다. 위에서 말했다시피 thread는 개수가 겨우 1024개밖에 안 되기 때문에 몇 개일 때 최적의 값을 가질지 한 번 검색을 해봤더니, 알고리즘마다 case by case인 것 같더라고요. 제 알고리즘에서 이를 계산해보니 아래와 같은 그래프가 나왔습니다. 네, 정말, thread 한 개 쓰는 건 무식한 짓이라는 것이 너무 자명하게 보이죠. (지금 다시 그래프를 그려보니 100배까진 차이가 안 나네요, 처음 알고리즘을 도대체 어떻게 짰었길래...)

사실상 42 thread 정도 돌리면 이후는 거의 엇비슷한 속도가 나옵니다. 그 이후는 돌릴 때마다 누가 빠른지 조금씩 다르더라고요. 그래서 저는 fractal 그리는 프로그램은 162 thread로 작성했습니다.


이렇게 간단히 fractal 그리는 프로그램을 만들면서 기본적인 최적화를 해봤습니다. 그리고 CUDA sample에 나와있는 의미심장한 loop를 풀어 둔 것을 검색하면서 또 다른 것을 배웠죠. 다음 글에서 다뤄볼 예정입니다.


오랜만에 글을 써 봅니다. 근래에 학업 공부를 하고 그러다 보니까 블로그에 공부한 걸 잘 안 올렸네요.(나름 자료를 찾아보고 틈틈히 보긴 했는데 쩝)


  2018년 겨울방학에 들어서고, 꽤 전부터 생각해오던 CUDA를 이용한 프렉탈 그리기를 직접 프로그래밍했습니다. 중학교 때 프렉탈을 처음 알게 되고 나서, 그 신비함과 아름다움에 빠져서 언젠가는 꼭 프렉탈을 그려내는 프로그래밍을 하겠다고 다짐을 했는데(그 옛날에 julia set의 상수마다 이미지를 만들어서 1TB 하드를 꽉 채우겠다는 생각도 해본 거 같습니다. 뭐 정작 여러 가지 그려보다 보니 이쁜 모양이 나오는 julia set 상수는 그렇게 많진 않았지만요)겨울방학 들어서고 하게 되었네요.


  요즘엔 안드로이드 프로그래밍을 거의 안 하고(앱 유지보수 정도...) 딥 러닝 등을 Python으로 하고 있습니다. 그래서 이번 프렉탈 그리기는 제가 옛날부터 주로 쓰던 Java AWT라던가 그런 걸로 만들지 않았고, Python 3에다가 PyQt5와 PyCUDA를 활용해서 만들어 봤습니다. 아래 이미지들이 제가 지금 제작한(그리고 제작하고 있는) 앱의 스크린샷입니다.

 

(GitHub 링크: https://github.com/AMakeApp/FractalViewer)


  이러한 프렉탈을 그리는데는 사실 CPU를 써도 크게 상관은 없습니다. 단지 GPU를 쓰는 이유는 프렉탈을 그리는데 들어가는 알고리즘이 상당한 연산을 필요로 하기 때문입니다. 이 연산 과정을 알려면 위의 프렉탈들이 어떻게 만들어지는지 알아볼 필요가 있습니다.


  제가 현재 앱에 구현해 둔 프렉탈은 위 두 이미지인 Mandelbrot Set과 Julia Set입니다. 사실 이 둘은 모양이 상이함에도 상당한 상관관계가 있습니다. 왜냐하면 이 둘의 집합을 계산하는 과정이 상당히 유사하기 때문이죠. 그렇기에 좀 더 많이 알려져 있는 Mandelbrot Set에 대해 알아봅시다. Mandelbrot Set은 이름에서 보이듯이 Mandelbrot가 고안한 집합입니다. 사실 많이 알려져 있듯이 저렇게 알록달록 해야지 Mandelbrot Set은 아니고 수학적으로는 아래 이미지처럼 복소평면 상에서 검정색 점들의 집합이 Mandelbrot Set입니다.

Mandelset hires


이 집합은 일반적으로 우리가 집합을 정의할 때와는 조금 다르게 특이하게 정의되어 있는데, 다음 점화식에서 수열이 발산하지 않게 하는 복소수 $c$의 집합으로 정의되어 있습니다.

$$z_0 = 0, z_{n + 1} = z_n^2 + c$$


즉, 이 집합은 무한 집합일테고 복소평면 상의 어느 한 점에 대해 이 점이 Mandelbrot Set에 속하는지 계산하려면 각 복소수에 대해 수많은 반복 연산을 통해 수열의 발산 여부를 확인해야 합니다. 다행히도 $| z_n | > 4$라면 발산한다고 볼 수 있기 때문에 일정한 반복 연산 후 $z_n$의 절대값을 비교하면 좀 더 수월하게 계산 할 수 있습니다.(아마 이 부분이 수학적으로 증명되어 있는 거 같습니다. 이 문서를 참고하세요) 하지만 그렇다고 해도 수많은 반복 연산이 필요한 것은 사실입니다. 초중고등학교에서 배우는 것처럼 단순히 함수꼴로 구할 수 있는 것도 아니고, 각 점에 대해 일일히 노가다를 해야하는 것과 마찬가지니까요. 각 점에 대해서는 제가 대충 해본 결과 200번 정도 이상하면 눈으로 보기에는 프렉탈이 충분히 이쁘게 나옵니다. 커다란 프렉탈 이미지를 생성하려고 2000 x 2000의 프렉탈 이미지를 생성한다고 합시다. 대략 이정도면 200 * 2000 * 2000 = 8억 번 정도의 연산이 필요로 합니다. 일반적으로 한 알고리즘에 대해서 1억 번 연산에 대한 소요시간을 1초로 잡을텐데(요즘 CPU는 더 빨라서 더 많이 연산을 할 수는 있습니다) 프렉탈 이미지를 계산하기 위해서는 8초나 걸린다는 겁니다. 요즘 CPU는 중사양 CPU도 4코어 8쓰레드 정도 가질텐데, 멀티 코어 프로그래밍을 한다고 해도 최소 1초는 걸린다는 이야기가 됩니다.


  이렇게 CPU는 프렉탈 이미지를 계산하는 데는 상당히 오래 걸리기 때문에 GPU의 수많은 코어를 사용해서 더 빠르게 계산을 할 수 있습니다. 비유를 하자면 CPU는 고급 인력 4~8명이 일하는 것이라면 GPU는 초보자 수 천 명이 일을 하는 것과 비슷합니다. 프렉탈 연산이 많은 반복 연산이 필요로 하지만 정작 그 연산 자체가 그렇게 복잡하지 않기 때문에(특히 분기 구문 같은 것이 많지 않기 때문에) 이러한 경우에는 GPU에서 빠르게 계산할 수 있습니다. 이러한 이유로 프렉탈을 빠르게 그려내기 위해서 GPU를 활용했습니다.


  GPU로 그려내기로 결정하고 나서, 제 컴퓨터에 장착되어 있는 GTX970에서 GPGPU 프로그래밍을 하기 위해서 Nvidia에서 지원하는 CUDA를 활용했습니다. 여기서 CUDA는 일반적으로 CUDA C를 사용해서 C/C++과 함께 사용되는데, GUI로 이미지를 보여주면서 편하게 프로그래밍하고 싶었기 때문에 Python 3를 기반으로 CUDA를 사용할 수 있게 만들어 둔 PyCUDA를 사용했습니다. 그리고 유려한 GUI를 보여주는 Qt를 Python에 접목시킨 PyQt5를 사용했고요.


다음 글부터는 이 Fractal을 그리는데 어떻게 CUDA 프로그래밍을 했는지 제 시행착오와 함께 CUDA에 대해 이야기해보겠습니다.

본 글은 필자가 Ubuntu 16.04.1 64bit 기반의 Unity와 Gnome을 약 6개월 정도 써보고 기타 다른 Linux를 깔면서 겪은 각종 문제들을 정리해둔 것입니다. 아마 계속 업데이트 될 거 같네요.


1. 부팅 문제

부팅이 실패하는 경우는 원인이 무진장 많습니다. 그러나 제가 경험해보니 원인은 거의 하나에 편중되어 있는 거 같더라고요. 그 원인을 순위별로 나타내서 해결법까지 말씀드려보겠습니다.


- 1위. 그래픽 문제

특히, Nvidia 그래픽 카드(왜 리누즈 토르발스가 Nvidia를 욕하는지 알 수 있는 경우입니다)를 쓰는 유저의 경우 처음에 OS를 깔 때 아예 Live CD 조차 GUI 부팅이 안 되는 경우가 있습니다. 또는 데스크탑에서 리눅스 잘 쓰다가 각종 패키지를 업데이트했을 경우(특히 아마 유저가 개발자라면 더 심할 거 같습니다) 기존의 리눅스 그래픽 드라이버와 충돌이 나는지 부팅이 안 되는 경우가 있습니다. 이런 경우에는 제 경험상 아래와 같은 현상이 나타납니다.


    - 1. Live CD로 부팅할 때 리눅스 펭귄 8마리 정도(모니터 크기, 해상도에 따라 다를 겁니다)가 떠 있고 그 이후 어떠한 그래픽의 변화도 일어나지 않는다.

        ↳ CentOS Live CD로 부팅시 발생했습니다.

    - 2. 부팅 로그가 뜨다가 'ACPI PCC Probe Failed' 등 probe 뭐시기가 실패했다, 오류가 났다는 등의 로그가 뜨고 진행이 안 된다.

        ↳ 거의 웬만한 Linux를 깔거나 깔려있는 상태에서 부팅할 때 발생했습니다.

    - 3. 부팅은 정상적으로 된 거 같은데 정확한 계정 정보로 로그인을 시도했음에도 불구하고 로그인 화면이 끊임없이 반복되고 메인 화면으로 이동할 수 없다.

        ↳ Ubuntu Unity에서 Nvidia Driver를 깐 직후 또는 특정 상황(업데이트를 했던가 등)이후에 재부팅했을 경우 발생했습니다.

    - 4. 부팅 화면이 정상적으로 뜨다가 로그인 화면이 나와야 하는데 모니터 백라이트가 깜빡거리면서 정상적으로 GUI 화면이 뜨지 않는 경우

        ↳ Ubuntu Gnome에서 Nvidia Driver를 깐 이후 특정 상황(업데이트를 했던가 등) 이후에 재부팅했을 경우 발생했습니다.


실제로 위의 상황들은 아마 Nvidia 그래픽카드를 쓰시면서 업데이트를 자주하시거나 저처럼 개발자이시면 꽤 많이 만나 볼 수 있지 않을까 싶습니다. 해결 방안은 다음과 같습니다.


    - 1,2번의 경우에는 grub 창(Ubuntu, Advanced Options, Memory Test 등의 옵션이 있고 방향키로 옵션을 선택할 수 있는 화면)에서 원하는 옵션

       (맨 위에 있는 디폴트 옵션 추천)에 선택을 둔 다음에 엔터 누르시지 마시고 e(edit)를 누르셔서 명령어를 수정하셔야 합니다. edit 창 잘 들어오셨으면

       각종 부팅을 위한 grub 명령어들이 모여있는 창이 뜰텐데 여기서 quiet splash 있는 줄에서 splash 뒤에 적절한 곳에 nomodeset을 넣어주시면 됩니

       다. 그리고 나서 F10 또는 Ctrl+X를 통해 부팅을 시도하시면 일단 부팅은 제대로 될 것입니다. 이후에 grub 옵션을 따로 건드셔서 그 옵션에

       nomodeset을 넣어주시면 추가적으로 큰 문제는 발생하지 않으실 겁니다.

    - 3번의 경우엔 Nvidia Driver를 깔 때 Driver 내부에 있는 OpenGL도 같이 설치하셨거나 아니면 업데이트로 인해 드라이버가 충돌난 것으로 보입니다.

       일단 로그인 창까지 오셨으면 Alt+Shift+F1을 누르셔서 CLI 콘솔 모드로 접속하셔야 합니다. 이후에는 계정 정보 입력하시고 Nvidia Graphic Driver

       Installer 설치하시던 것처럼 그대로 설치 진행하시면 됩니다. 이때 OpenGL 옵션이 보인다면 No를 선택하셔서 설치를 막으셔야 합니다. 경험상 apt 등

       으로 설치한 Nvidia Driver는 꽤나 충돌이 잘 나고 문제가 많았기 때문에 저는 Nvidia 공식 홈페이지에서 제공하는 .run 확장자의 드라이버를 추천드립

       니다. .run 확장자의 드라이버를 까는 방법은 콘솔 모드로 들어가셔서 Ubuntu Unity의 경우 'sudo systemctl stop lightdm', Ubuntu Gnome의

       경우 'sudo systemctl stop gdm'으로 GUI 서비스 죽인 후 root 계정으로 드라이버 파일을 실행해서 설치하시면 됩니다. 시간이 나면 나중에 싹 다 정리

       해서 리눅스에서 그래픽카드 드라이버 설치 방법도 안내해드리겠습니다.

    - 4번의 경우엔 일단 GUI 조차 제대로 뜨지 않았고, 게다가 제 컴에서만 그러는지는 모르겠는데 Alt+Shift+F1 등이 먹히지도 않아서 CLI 콘솔 창으로 접속

       이 불가능하더라고요. 그래서 먼저 재부팅을 하신 다음에 grub 창으로 가야합니다. 만약에 grub창이 뜨지 않으시면 리눅스가 부팅화면 뜨기 직전(저 같

       은 경우엔 부팅 화면 직전에 '-'이 깜빡거리는데 그때)부터 grub 옵션창이 뜨기 전까지 Shift 키를 그대로 쭉 누르고 있으면 grub 창이 뜹니다. 여기서 맨

       위에 디폴트 옵션 가시고 e(edit)를 누르셔서 명령어를 수정하셔야 합니다. 명령어 수정창이 뜨면 거기서 splash 있는 줄까지 오신 다음에 'quiet splash

       vt.handoff=7(또는 $~handoff 있는 명령어)'(아마 이 세 개가 다 연속적으로 있을 겁니다.)를 다 지우시고 거기에 'single'을 입력하시고 Ctrl+X 또는

       F10으로 부팅하시면 콘솔창이 뜹니다. 이후엔 위에서 설명한 Nvidia Driver 까는 방법을 그대로 따라하셔서 드라이버를 다시 까시면 됩니다.


- 2위. 디스크 파티션 문제

저 같은 경우엔 NTFS의 하드를 부팅 시에 fstab을 통해 자동 마운트를 시키는데 이게 윈도를 쓰다가 리눅스 부팅할 때 가끔씩 디스크 내부에서 꼬이는 건지 마운트 자체가 에러가 나서 fstab도 오류나고 이로 인해 부팅 자체가 멈춰버리는 경우가 있습니다. 이런 경우에는 제 경험상 아래와 같은 현상이 나타납니다.


    - 1. 부팅화면 잘 뜨고 프로그래스 바 같은 것도 잘 돌아가는 등 그래픽이 정상적으로 동작하다가 어느 순간 멈춰버리는 경우

    - 2. 부팅하다가 또는 부팅할 때 로그를 켜뒀을 때 부팅 오류라면서 Emergency Mode로 들어가는 경우


뭐 저야 이게 파티션이 망가진 게 아니고 일종의 버그 같은 거라서 저는 되게 쉽게 해결했지만 아닌 분들도 있게 추가적으로 제가 아는 한에서 해결 방안을 더 알려드리겠습니다. 1,2번에 대한 해결 방안은 아래과 같습니다.


    - grub 창에 들어가서(자동으로 안 뜨면 부팅 할 때 Shift 키 누르고 있기) Advanced Options -> 리눅스 커널 버전-recovery mode에 들어가시면

       부팅이 됩니다. 그 다음에 잘 보시면 파티션 오류 잡는 거 있는데 그거 실행해주시면 아마 될 겁니다.(이건 제가 진짜 파티션이 망가져 본 적이 없어서 제대

       로 해본 적이 없긴 하네요.

    - 저 같이 리눅스 기본 파티션 말고도 다른 것을 추가적으로 fstab으로 자동 마운트하시고 윈도와 함께 듀얼 부팅하신다면 그냥 윈도 다시 한 번 부팅하셨다

       가 뭐 이대로 끝내기는 좀 아쉬우니 문제있는 해당 디스크 윈도에서 잘 인식되는지 확인하시고 디스크를 탐색기로도 열어보시고 다시 리눅스 들어가시면

       됩니다(...).


2. 사용중 문제

그래도 윈도나 맥보다는 안정성이 조금 떨어져서 은근 문제를 많이 겪었으나 딱히 그렇게 굵직하게 사용상에 큰 지장을 주는 경우는 많이 못 봤습니다. 제가 경험하고 해결한 문제들만 보여드리겠습니다.


- 1. 키보드 & 마우스가 사용 중에 갑자기 멈춰버린다.

↳ 답이 없습니다(...). 다른 USB 포트에 키보드와 마우스를 끼워보시고, 그래도 안 살아난다면 강제로 재부팅을 하는 수 밖에 없습니다. 아마 고질적으로 가끔

     씩 Ubuntu에서 발생하는 문제로 보이는데 저도 아직까지 완벽한 해결책은 찾지 못했습니다.

- 2. Firefox를 실행하는데 분명히 다른 Firefox 프로세스가 실행되고 있지 않음에도 제대로 실행할 수 없다.

↳ 이건 설치하고 초기 실행할 때 제대로 안 했기 때문에 그럽니다. 사실 apt 등으로 firefox를 설치하신다면 죽어도 만날 수 없는 오류라고 전 생각합니다. 저

     같은 경우는 처음에 Firefox Developer Edition을 /opt/폴더 내부에 옮겨서 설치한 후에 'root' 권한으로 Firefox를 실행했는데 이때 초기 설정 파일들

     이 'root' 권한으로 생성되어서 이후에 일반 'user' 권한으로 기존의 Firefox를 실행하면 그 파일들을 불러오지 못해서 발생하는 오류라고 봅니다.

     (Chrome/Chromium은 이걸 알고 있었는지 'root' 계정으로는 죽어도 실행 못하게 만들었더라고요. 왜 그런가 했더니 이런 빅픽쳐가...)  해결방안은

     먼저 firefox를 지우시고(Developer Edition은 그 폴더 자체를 삭제) 이후에는 아래 폴더들을 완벽하게 삭제하시고 재설치하시면 됩니다.

     ~/.mozilla/firefox/

     /etc/firefox/

     /usr/lib/firefox/

     /usr/lib/firefox-addons/

어쩌다가 소설 '개미'를 읽게 되어서 그 유명한 개미수열을 한 번 Python으로 구해보고 싶어져서 한 번 구해봤습니다.


일단 이 수열은 원래 읽고 말하기 수열입니다. 한국에서는 소설 '개미'로 인해 유명해져서 개미 수열이라고 부른다고 하군요. 재미난 점(?)이 서양(아마 서양쪽이 맞을 겁니다)과는 다르게 우리나라에서는 '1'을 '일이 한 개'라고 읽고, 서양에서는 '1'을 '한 개의 일'(one 1)라고 읽기 때문에 실제로 소설이 한국어로 번역될 때 한국 사정을 고려하다보니 한국에 출판된 '개미'에 나오는 수열은 읽고 말하기 수열를 뒤집은 꼴입니다. 예를 들어서 원래 읽고 말하기 수열은

1,

11,

21,

1211,

...


이렇게 이어지는데 반면에 한국에 출판된 '개미' 에서는

1,

12,

1121,

...


이렇게 나옵니다. 뭐 이 구조 특성상 프로그래밍하는 데도 순서만 바꾸면 되는지라 저는 한국 소설에 나온 방식이 더 맘에 들고 실제로 '개미수열'하면 이렇게 알려져 있는 경우가 더 많은 거 같아서 후자의 방식을 선택하여 프로그래밍 해봤습니다.


Python 코드는 다음과 같습니다. 일반적인 터미널 출력과 더불어 파일 출력도 가능하게 만들었습니다.

#-*- coding: utf-8 -*-

n = input("출력할 수열의 끝 번호: ")
isSave = raw_input("파일로 저장할 것인가요?(Y/N)(기본: N): ")

if isSave == "Y":
    f = open("./Les-fourmis_sequence.txt", "w")

s = "1"
for i in xrange(n):
    if isSave == "Y":
        f.write(s + "\n")
    else :
        print "\t" + str(i + 1) + ": " + s

    x = s[0]
    count = 1

    s_dev = ""

    for j in xrange(1, len(s)):
        if s[j] != x:
            s_dev += str(x) + str(count)

            x = s[j]
            count = 1
        else:
            count += 1

    s = s_dev + str(x) + str(count)

if isSave == "Y":
    f.close()

이 수열의 특성상 거의 기하급수적으로 길이가 길어지기 때문에 1번째부터 15번째 수까지만 보여드리겠습니다.

1
11
12
1121
122111
112213
12221131
1123123111
12213111213113
11221131132111311231
12221231123121133112213111
1123112131122131112112321222113113
1221311221113112221131132112213121112312311231
11221131122213311223123112312112221131112113213111213112213111
122212311223113212223111213112213111211223123113211231211131132111311222113113
...


이 수열의 재미난 성질이 있다면

1. 초기값(1)이 달라지지 않는다면 각 수에서 1, 2, 3을 제외한 다른 숫자들은 나올 수 없다.

↳ 상당히 흥미로운 이야기입니다. 나중에 가능하면 한 번 증명해보고 싶네요.

2. 초기값이 22를 제외한 임의의 수이면 수열은 끊임없이 길어진다.

↳ 간단히 생각해보면 간단한 이야기입니다. 먼저 초기값이 어떠한 수이던 간에 2번째 수부터는 무조건 짝수입니다. 근데 초기값이 한 숫자로만 이뤄져있으면

     당연하게 2번째 수는 무조건 두 자리일 수밖에 없습니다. 따라서 22이면 22, 22, 22, ...으로만 이어집니다. 즉, 초기값이 22가 아니라면 어떻게든 그 수열

     의 길이는 끊임없이 길어지게 되어 있습니다.

3. 초기값이 22를 제외한 임의의 수이고 각 수열의 일반항의 길이를 Li라고 하면

라고 합니다. 이 상수를 콘웨이 상수라고 하며 대수적 수라고 하네요. 나중에 시간나면 이놈도 한 번 구해보면 나름 재미있을 거 같습니다. ㅋㅋㅋ


지금 이 글 쓰면서 수열의 100번째 수까지 구해서 저장하고 있는데... 이런 짓은 안 하시는게 정신건강에 좋습니다. 파일 용량이 텍스트 주제 5GB를 넘어가고 있네요...(물론 저는 1부터 200억 사이에 있는 소수를 구하면서 11GB에 육박하는 텍스트 파일을 가지고 있긴 힙니다 ㅋㅋㅋ) 게다가 시간도 만만찮게 오래 걸립니다. 대충 지금 실행시간 20분 넘어간 거 같네요. 한 번 나중에 시간 복잡도 O()를 구해보는 것도 좋을 거 같네요.


(참고: https://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%EC%96%B4%EC%8A%88%ED%8A%B8%EB%9D%BC%EC%8A%A4_%ED%95%A8%EC%88%98)


어쩌다가 우연히 이 함수를 알게 되었는데, 그냥 개인 취향으로 맘에 들어서 언젠간 한 번 그려보고 싶었던 놈이였습니다. 오늘 새벽에 멍 때리다가 갑자기 생각나서 python numpy를 활용해서 그려봤네요. 거의 수학 공식 그대로를 코드로 바로 옮겨서 쓸 수 있다는 게 맘에 들었습니다. 실제로 이걸 C/C++, Java로 계산하자면(까마득...) 확실히 python이 편하긴 하네요.


코드는 다음과 같습니다.


import numpy as np import matplotlib.pyplot as plt a = 0.5 # 0 < a < 1 b = 5 # ab > 1 + 3/2 * pi x = np.arange(-5, 5, 0.0001) y = np.zeros(2 * 5 * 10000, dtype="float128") for n in xrange(1000): y += np.power(a, n) * np.cos(np.power(b ,n) * np.pi * x) if n % 100 == 0: print "Now: ", n plt.grid(True) plt.xlim(-5, 5) plt.ylim(-3, 3) plt.plot(x, y, "black", linewidth=0.1) # linewidth 조정 가능 plt.savefig("Weierstrass Function.png", dpi=1200) # 그냥 보시려면 plt.show()


이미지로 그려봤습니다. 나름 적절히 linewidth 타협을 봐서 세세하게 잘 보이면서 너무 얇지도 않게(?) 그렸습니다. 너무 얇다고 생각하시는 분은 linewidth를 0.1보다 크게 세팅하시면 됩니다.

* 그리다보면 warning으로 overflow가 뜰 수 있습니다. np.power의 특성 덕분인지는 모르겠으나 그래프 그리는데에는 큰 지장은 주지 않아서 그대로 사용했습니다. 원래는 a 초기값에서 step마다 a 자신을 초기값과 곱해서 늘려가게 짜보았으나 이건 overflow가 나버리면 아예 작동에 심각한 지장을 줘서 일단은 np.power로 했습니다. 따로 제대로된 해결책을 찾아봐야 할 것 같습니다.

저는 현재 3개의 모니터를 동시에 쓰고 있습니다. 한 개는 가로로 두고, 나머지 두 개는 세로로 둬서 코딩하는데 쓰는데, 모니터 세 대가 종류가 다 달라서 크기도 가지각색이고 그럽니다. 뭐 아무튼 이 환경에서 Ubuntu 16.04.1과 Windows 10을 멀티부팅해서 쓰는데, 윈도에서는 각 모니터마다 배경화면을 달리 정할 수 있지만, Ubuntu에서는 기본적으로는 불가능합니다. 좀 당황해서 처음에는 검색하면서 여러가지 다 시도해봤는데 다 안돼서 좌절했는데, 오늘 다시 해보니까 되더라고요(음?) 이 방법을 소개해보려고 합니다.


참고한 곳은 여기입니다. (http://askubuntu.com/questions/390367/using-different-wallpapers-on-multiple-monitors-gnome-2-compiz) 처음에 여기 방법을 시도하다가 잘못해서 성공 못 해서 다른 곳도 찾아봤는데, 진짜 이거 말고는 답이 없어보입니다.


일단 먼저 배경화면으로 설정할 사진들을 여럿 준비하시고, nitrogen과 gnome-tweak-tool이라는 프로그램을 깝니다.


sudo apt install nitrogen gnome-tweak-tool


여기서 일단 gnome-tweak-tool을 실행합니다. 아마 gnome 환경에 대한 세세한 설정을 할 수 있게 해주는 프로그램인 거 같네요. 여기서 Desktop을 들어가시고 Icons on Desktop을 OFF로 둡니다. 이거 안 하면 배경화면을 암만 바꿔도 설정된 게 보이지 않더군요. 그리고 이거 끄면, 바탕화면에 어떠한 아이콘을 둘 수 없다는 것을 염두하셔야 합니다. (Windows의 바탕화면 아이콘 표기 안 하기랑 같은 기능 같네요)


다음으로 nitrogen을 실행합니다.


실행한 후에 Preferences에서 바탕화면 사진들이 들어있는 경로 폴더를 추가해줍니다.

이후 OK를 누르시면 그 폴더에 있는 사진들이 뜹니다.  (쿨럭, 제가 바로 아이유 팬입니다!)


그 사진들 중에서 하나 선택하시고 Automatic이 있는 곳을 통해 사진 설정(꽉 채우기, 바둑판식 채우기 등)을 하시고 어디 모니터에 하실지 선택하신 후 Apply해주시면 배경화면이 설정됩니다! 저는 아래와 같이 세팅해뒀습니다~~~


아 그리고, 이 nitrogen으로 설정된 배경화면은 세팅한 이후로 재부팅하면 사라지기 때문에 Launcher에 있는 Search your computer을 클릭하신 후 Startup Applications을 클릭하시고 여기서 다음 명령어를 시작 프로그램에 추가해주시면 됩니다.


nitrogen --restore


참고로 재시작한 이후에 로그인 하시고 한 10초 정도? 기다리셔야지 바뀐 배경화면들이 다시 적용되어서 보입니다. 아마 시작 프로그램의 딜레이 때문 아닐까 싶네요.

음, 1시간 동안 Minecraft 아이콘 삽질을 해보면서 한 번 남겨보면 좋을 거 같아서 남겨봅니다. 일단 Ubuntu 바로가기 아이콘은 종류가 대략 두 가지로 나뉠 거 같은데, 전 바탕화면 따위를 더럽히고 싶지 않아서 아래와 같이 Launcher라고 불리는 구역에 바로가기 아이콘을 넣는 형식을 소개할 겁니다.

아이고 이미지 참 기네요. 여튼 이 구역에 저기 중앙 즈음에 있는 마인크래프트 크리퍼 아이콘처럼 바로가기를 넣어볼 것입니다.


1. sudo vi /usr/share/applications/이름.desktop 이 명령어로 바로가기를 생성할 수 있습니다. 우리는 저 Launcher에 넣는게 목표이기 때문에 주로 각종 앱들의 바로가기 파일들이 저장되어 있는 /usr/local/applicaitons에 생성합니다. 이후 아래와 같이 편집할 수 있습니다.

[Desktop Entry] Version=x.y                        # 프로그램 버전번호(1.0 등) Name=프로그램 이름 Comment=프로그램 설명 Exec=프로그램 실행 명령어 Icon=프로그램 아이콘 이미지 경로 Terminal=false                     # 터미널 실행여부(true: 실행, false: 실행 안함) Type=Application                   # 형식이 앱이다. 웬만해선 이건 수정 안 해도 됩니다. Categories=Utility;Application;    # 카테고리인데 저 같은 경우는 귀찮기도 하고 그래서 이 옵션 자체를 안 쓰긴 합니다만

# https://specifications.freedesktop.org/menu-spec/latest/apa.html 참고 가능합니다.


2. :wq로 저장한 후 sudo chmod +x 이름.desktop 으로 실행권한을 줍니다.

3. 윈도우의 시작버튼이라고 할 수 있는 우분투의 시작버튼을 눌러 검색창에서 그 프로그램 이름치면 나옵니다. 안 나오는 경우 /usr/share/applications 가서 직접 저 프로그램 실행해보시고 오류 뜨시면 명령어 수정하셔야합니다. 전 이거 명령어 문제 땜에 안 되더라고요. 여튼 아이콘 뜨면 그거 런쳐에 박으시면 끝!

이전에 제 데스크탑에 각종 리눅스(Deepin OS, Ubuntu, Debian, Fedora, Elementary OS 등)를 설치해보면서 겪어본 바로는, 생각보다 리눅스 호환성이 좋지는 않다(......)는 것입니다. 그래서 한 번 설치기를 올려보려고 합니다. 저 같은 경우는 한 20시간 삽질하면서 해봤네요.


일단 제 데스크탑 기준으로 설명할 것입니다. 사양은 다음과 같습니다.

CPU: Intel i7-5820K

RAM: 16GB

Mainboard: MSI X99S SLI PLUS

Graphic Card: GTX970

HDD: SATA2 Seagate 320GB로 추정됨


1. 일단 원하는 리눅스를 다운 받습니다. 저 같은 경우는 Ubuntu 16.04(현재 최신 Ubuntu LTS 버전)을 다운받았습니다.

2. USB 이동식 디스크에 리눅스 iso 파일을 굽습니다. 이때 추천해드리는 툴이 Rufus입니다. 개인적으로 많이 애용하고, 다른 툴에 비해 호환성도 좋더군요.

3. iso 파일을 구운 USB 이동식 디스크를 넣고 부팅합니다. BIOS 창에서 USB 이동식 디스크를 부팅 옵션 최상단에 두거나, 저 같은 경우 F11을 눌러서 부트 메뉴에서 선택할 수 있었습니다.

4. 이제 기본적인 grub(주로 쓰이는 리눅스 부트로더)가 보입니다. 이때 한 번 Install OS 또는 Start OS 등을 눌러서 부팅을 시도해봅니다. 저 같은 경우는 이후 화면이 이상하게 바뀌거나 검정색이 되면서 아무것도 되지 않았습니다. 원인은 Nvidia 그래픽카드 때문이죠. (리누즈 토르발스가 엔비디아에 욕을 날린 이유가 분명 있습니다 ㅇㅇ) 따라서 다시 컴퓨터를 재시작하고 다시 grub 화면까지 진입한 후, e를 눌러 명령어 수정을 시도합니다. 잘 찾아보면 대체적인 Desktop Linux 버전에서는 아마 splash 명령어가 보일겁니다. 거기 앞 또는 뒤에 nomodeset을 넣어줍니다. 그리고 F10인가를 눌러서 부팅을 시도합니다. 아마 잘 될 겁니다.

5. 부팅을 시도한뒤 언어를 설정하고 맘대로 설치하시면 됩니다. 개인적으로 추천해드리고 싶은 파티션 구조는 /boot에 500MB정도 할당, swap에 자신의 램의 1~2배 할당, 나머지를 /에 할당하는 겁니다. 귀찮으시면 Default 옵션으로 가셔도 되고요.

6. 설치 후 이제 리눅스 GUI 화면에 진입했을 것입니다. 일단 grub 부트 옵션을 부팅할 때마다 일일히 넣어줄 수 없으니, 수정해서 넣어야 합니다. 

sudo vi /etc/default/grub 으로 grub 부트 옵션을 수정할 수 있습니다. 아래와 같은 화면이 나올텐데, 뭐 GRUB_CMDLINE_LINUX에 nomodeset만 넣어도 충분하지만, 저 같은 경우 언제 또 리눅스가 죽을지 모르기 때문에(ㅠㅠ) 부트 로그를 보여주지 않는 옵션인 splash quiet 옵션을 지우고 넣었습니다. 저처럼 하시면 grub에서 선택 후 멋-진 리눅스 부팅 로그를 구경하실 수 있습니다 하핫

저 같은 경우는 트리플 모니터를 사용하는데 이 상황에선 하나 밖에 인식이 안 됩니다. 그래픽카드 드라이버가 깔리지 않았기 때문이죠. 이제 깔아주러 갑니다. 가능하면 검색해서 나오는대로 까시지 말고(전 그렇게 했다가 무한로그인 만나고 GG 쳤습니다) 제 방식대로 하시면 잘 될거라 생각됩니다.

7. 구글에 검색해보시면(nvidia linux driver 등...) 엔비디아에서 다운받을 수 있는 리눅스 드라이버가 있습니다. 이때 파일 확장자를 .run을 선택하시는 걸 추천드립니다.(딱히 증명된건 아니지만 일단 전 잘되었거든요 쿨럭...) 저는 NVIDIA-Linux-x86_64-367.35.run 를 다운받았네요.

8. 다운 받은 후 드라이버를 깔기 위해서 GUI 모드를 끕니다. Ubuntu의 경우, Ctrl + Alt + F1을 누르면 CLI 모드에 진입할 수 있습니다. 진입한 후, 일단 su로 root 계정 로그인 후 service lightdm stop으로 GUI를 끌 수 있습니다.

9. 종료 후, run 파일을 찾아서 실행합니다. 적당히 동의해주시면 됩니다. 참고로 저는 모든 곳에서 다 동의했습니다. 듣기로는 리눅스 드라이버 깔 때 OpenGL을 깔 것이냐가 뜰 수도 있는데, OpenGL 까는 건 무시해야 나중에 무한 로그인화면이 뜨지 않는다고 하더군요. 전 그런 창 뜨진 않았네요 :)

10. 다 까신 후, 재부팅하시고 무한 로그인 화면만 안 뜨시면 어느정도 성공하신 겁니다!


뭐 개인적으로 디자인이 이쁜 Deepin OS나 Elementary OS를 쓰고 싶었는데, 제 컴에서 아예 부팅조차 되지 않는 괴랄한(...) 현상이 보여서 시도조차 못 해본게 조금 아쉽긴 합니다.

  1. 개발자 [0] 2017.01.15 13:44 신고

    감사합니다!!
    그래픽 카드 때문에 계속 말썽이었는데 정보가 도움 됬어요

  3월 초 즈음에 주문했던 Intel Realsense SR300 모델이 드디어 지난달 마지막 주에 도착했습니다!(물론 시험은 망했습니다...쿨럭)

뭐 여튼 거의 두달 만에 받는 상품인지라 되게 기대하고 까봤습니다.



상품 구성은 상당히 간단했습니다. 달랑 저 박스 하나였고, 저 박스 하나에 리얼센스 카메라 한 개랑 설명서(?) 같은 것들만 있었습니다 (값어치 안 하는 기분이 쿨럭)  아래 사진은 리얼센스 카메라를 설치한 모습입니다.

뭐 나름대로 괜찮아 보였습니다. 단점이라면....

1. 생각보다 호환성이 좋지 않다: 지원 스펙을 보면 6세대 이상의 CPU만을 지원한다는데 그거 때문인지 뭔지는 모르겠지만 USB 인식이 병맛 같았습니다.

2. 고주파음: 최악입니다. 크지는 않지만 리얼센스 카메라가 작동될 때 미세한 삐이이~ 소리가 들립니다. 카메라 불량인가 싶어서 포럼에도 질문을 올려봤는데, 미국분들이라 마음이 넓으신건지 그냥 쓰거나 케이스 만들어서 쓰라고(...)하시더군요. 나름대로 익숙해져서 쓰는 중입니다. 교환 받기도 애매할 꺼 같을 뿐더러, 귀찮습니다.

3. 생각보다 성능이 좋진 않다: 제 주관적 평가이긴 합니다만, 생각보다 3D scan이 좋은 편이 아니더라고요... 뭐 3D scan기능 쓰려고 산 건 아닌지라 어느정도 만족은 합니다. 아마 사람 얼굴 스캐닝하면 GTA4정도의 얼굴 랜더링에서 조금 미흡한 수준일 듯 합니다. 아, 그리고 안경 같은 물체는 인식 잘 못 합니다. 안경 쓰고 스캐닝하니까 얼굴에 안경 그대로 찍혀나오더라고요(뭔...)


  아래 이미지들은 예제 중 일부를 실행해본 모습입니다. 이상하게 Object 3D Scan은 잘 안되더라고요. 예제도 아주 좋은 편은 아닌 거 같다는 생각이 조금 들긴 했습니다. (제 얼굴 RGB 사진을 올리긴 뭐하니, Depth쪽 예제를 실행해봤습니다)



 나름대로 괜찮은 편입니다. 손 모양도 신기하게 잘 잡아내더라고요. 두번째 이미지가 손을 인식한건데, 우하단에 thumb_up을 눌러주면 저걸 Listening 하게 되어 위와 같은 제스쳐를 인식하여 밑에 로그처럼 나오게 됩니다.(예제 오류인지 왼손인지, 오른손인지 인식 잘 못 하는 건 함정)


  종합적으로 제가 계획하고 있는 프로젝트에는 적합하되, 아주 좋다고는 못 할 듯 합니다. 데이터 시트인가를 보면 실제로 리얼센스 기능들도 거의 다 베타, 알파로 정해져있더라고요. 다음주부터 본격적으로 C# 공부를 하면서 리얼센스 개발 수기를 쓸 예정입니다~

'Programming > Intel RealSense' 카테고리의 다른 글

1. Intel Realsense 도착! 및 예제 실행  (4) 2016.05.04
0. Intel Realsense 구매  (0) 2016.04.23
  1. 송민관 2016.05.25 09:51 신고

    안녕하세요, 저도 리얼센스에 관심이 있어, 인터넷을 검색하다 이 곳에서 구입후 사용에 대한 내용을 보고 글을 남기게 됐습니다.
    제가 궁금한 점은 리얼센스가 어두운 곳에서 동작인식이 되는지 궁금합니다 ^^
    혹시, 시간 되실때 시험해보시고 알려주실수 있으신지요 ^^
    초면에 이렇게 글을 남기게 되서 죄송합니다.
    된다면 저도 구입을 해볼까 생각중입니다 ^^
    꼭 좀 부탁드립니다.
    감사합니다 ^^

    • makeapp 2016.05.26 01:38 신고

      일단 제 방 불을 꺼보고(모니터는 일단 봐야 하니 끄진 못 했네요) 테스트를 해봤는데 동작 인식(V사인, OK사인 등)은 잘 되는 거 같네요. 아마 적외선 센서로 인식해서 그런거 같기도 합니다.

  2. dalboki 2017.12.26 14:30 신고

    안녕하세요...

    리얼센스 검색하다보니 님 블로그에 와서 좋은글 봤습니다..ㅎㅎㅎ

    혹시 리얼센스 카메라로 동작인식 (사람의 모양)도 가능 한가요?

    • makeapp 2018.01.16 03:55 신고

      거리 인식이 가능하기 때문에 사람을 누끼 뜨듯이 할 수는 있을 겁니다. 사람 자체를 인식해서 하는 건 있는지 잘 모르겠네요

## 2016.05.02 업데이트


제가 관심있는 오픈소스 프로젝트를 간단하게 정리해보려고 합니다(즐겨찾기에 쌓아두었더니 보지도 않아서...)


1. 시인 시팔이(욕 아닙니다): https://github.com/carpedm20/poet-neural

  딥 러닝으로 인간이 쓴 시를 토대로 새로운 시를 쓰는 AI입니다. 처음에 알게 되었을 땐, 그냥 소개 자료만 있었는데 어느새 오픈소스가 되어 있더라고요.함정은 실제로 체험을 해보고 싶었는데, UNIST쪽에서 AI 모듈을 날린 거 같네요. 404 뜹니다.


2. 알파고 레플리카: https://github.com/Rochester-NRT/RocAlphaGo

  어느 분이 알파고 논문(Nature지 링크, 전 4만원정도 내고 샀슴다(...))을 토대로 만든 알파고 레플리카입니다. 그냥 뭐...짱 신기해보입니다. 논문 읽으면서, 하나씩 번역하고 그러고 있는데, 원리는 알겠지만, 뭔 소리인지는 모르겠는.... 파이썬 기반입니다. 6살 때부터 바둑 둬서 바둑 되게 잼있어하는데, Google DeepMind Challenge Match 보면서 좀 무섭기도 하고 뭐 그랬습니다.


3. 예쁜 꼬마 선충 AI: https://github.com/openworm/OpenWorm

  아마 작년 이맘때쯤이었던거 같습니다. 예쁜 꼬마 선충 뉴런 구조를 이용해 만든 최초의 디지털 생명체(생명체라 하기도 뭐할 거 같긴 합니다)이죠. 관심 있게 보고, 막 이걸로 AI 로봇 만들어보려고 했는데, 역시 시간 부족(...프로젝트 관리 능력이 심히 떨어집니다)으로 관두고, 나중에 하고 싶은 프로젝트로 남았네요. 아마 오픈소스로는 뉴런 DB랑 파이썬으로 작성한 AI가 있는 걸로 압니다. 뉴런 DB는 다운 받아서 열어봤는데, 생물학에 문외해서 그런지 다 뭔소리인가 싶더라고요.


4. wego: https://github.com/schachmat/wego

  관심있는 프로젝트라기 보다는 좀 신기해서 담아두었던 프로젝트입니다. 무려 Go 언어 기반으로 CLI 환경에서 아스키 아트를 이용해 날씨를 알려줍니다. 깔아봤는데, 윈도에선 MSYS2 콘솔에서나 보기 편하지 명령 프롬프트나 파워쉘에선 절대 보기 좋진 않습니다. 설정 좀 건들여봤는데, 제 문제인지는 모르겠으나 제 컴에선 좀 깨져서 나오더라고요.


5. Web Captcha Bot: https://github.com/hletrd/SNU_sugangcaptcha

  아는 분이 작성하신 딥 러닝을 이용한 캡챠 봇인데, CNN을 사용했네요. 사실 연구과제로 캡챠 뚫는 딥 러닝 연구해보려고 했는데, 이 분이 이걸 만드셔서(...) 포기했습니다. 뭐 사실 이거 말고도 이미 크롬 앱으로도 캡챠 뚫는 수준의 프로그램이 나온 걸로 알고 있습니다.


6. Google TensorFlow: https://github.com/tensorflow/tensorflow

  구글에서 공개한 Deep Learning 라이브러리입니다. 성능은 그저 그런거 같은(Microsoft의 CNTK가 멀티 GPU에서 성능이 엄청 좋더라고요)데 무엇보다 검색했을 때 잘 나오고(어느정도 인지도가 있으니 질문 같은 것도 쉽게 할 수 있을 거 같네요), 무엇보다 튜토리얼이 잘 나와있어서 맘에 들어서 골랐네요. 일단은 텐서플로우로 딥 러닝 기초 쌓고 그 다음에 CNTK, Torch, Caffe 하고 싶네요. 아 참고로 텐서플로우는 윈도 미지원입니다. 쓰실려면 도커에 리눅스 깔아서 쓰시거나, 아니면 나중에 우분투 Bash 지원될때쯤 사용가능하지 않을까 싶네요. (Microsoft에서 발표한 퍼포먼싱 차트: ..여기선 거의 꼴등이긴 합니다 하하, 뭐 근데 어차피 상업용으로 공부하는 건 아니니 괜찮을 듯 하네요)

'Programming' 카테고리의 다른 글

관심있는 오픈소스 프로젝트  (0) 2016.04.23

+ Recent posts

티스토리 툴바