728x90

최근에 연구실에서 사용할 Cuda 를 찾아보다가, 최신 버전인 9.0을 설치하였고, cuDNN 7.0을 설치하였다.


그런데 위의 버전들은 torch 와 pytorch를 지원해주지 않는 것을 확인했다.


나는 tensorflow를 써서 상관이 없지만... 어쨋든 모두가 써야 하는 것이기에


cuda 8.0 버전을 설치하려고 nvidia developer 공식 사이트에 가보았지만 찾기가 힘들었다.


결국 구글링 끝에 주소를 찾았다...


https://developer.nvidia.com/cuda-toolkit-archive


cuDNN 예전 버전은 다음 사이트에서 받으면 된다.

(로그인이 필요함)


https://developer.nvidia.com/rdp/cudnn-download

cuda 9.0 과 cuDNN 7.0을 그대로 둔 상태에서 설치를 진행 할 것이다.


문제가 된다면 다음의 명령어를 통해 cuda 9.0 버전을 삭제하려고 한다.



To uninstall the CUDA Toolkit, run the uninstallation script provided in the bin directory of the toolkit. By default, it is located in /usr/local/cuda-9.0/bin:
$ sudo /usr/local/cuda-9.0/bin/uninstall_cuda_9.0.pl
To uninstall the NVIDIA Driver, run nvidia-uninstall:
$ sudo /usr/bin/nvidia-uninstall
To enable the Nouveau drivers, remove the blacklist file created in the Disabling Nouveau section, and regenerate the kernel initramfs/initrd again as described in that section.


아직 9.0 출시가 얼마 않되어 프레임워크 지원이 완벽하지 않은 것 같다...

728x90
728x90

바이두 Deep Voice Review

이 논문의 일부 아이디어는 매우 직관적이다.  Text to Speech Systems에 딥 러닝을 적용하는 Baidu의 Deep Voice를 다룬다.

Baidu’s Deep Voice

Arxiv Link: https://arxiv.org/abs/1702.07825

기관 : 바이두 리서치

최근 Andrew Ng의 Baidu AI 팀은 텍스트를 음성으로 변환하기위한 새로운 딥 러닝 기반 시스템에 관한 인상적인 논문을 발표했다. 


1. 분명히 Baidu의 결과는 MacOS의 프로덕션 TTS 시스템과 비교할 때 자연스럽게 들린다. 위의 내용은 한 가지 큰 경고로 볼 수있는데,  Baidu의 results 샘플들은 그 문장이 훨씬 더 인간이 말하는 것과 가까운 품질을 제공하고, 이 샘플들을 누군가는 또 Groundtruth의 training sample로 사용할 수 있다는 것이다. 또한 Baidu 샘플은 빈도 및 기간 데이터에도 액세스 할 수 있다.


그러나 출력의 품질을 넘어서 이 논문이 새로운 지평을 열었던 몇 가지 주요 방법은 바로 Deep Voice는 모든 TTS Pipeline에 Deep learning을 사용하였다는 것이다.

이전의 TTS 시스템은 파이프 라인의 여러 구성 요소에 딥 러닝을 사용했지만이 논문 이전에는 모든 주요 구성 요소를 신경망으로 대체하기 위한 연구는 없었다.


2. 딥 러닝을 사용하여 저자는 기존 파이프 라인에 비해 많은 기능 처리 및 엔지니어링을 피할 수 있었다. (이 말은 기존의 머신러닝의 HMM-State 등 복잡한 계산을 피하였다는 뜻으로 해석 됨) 이는 Deep Voice를 훨씬 더 일반적으로 만들어 다른 문제 영역에 적용 할 수 있다. 실제로 Deep Paper는 아래 논문의 저자가 설명한 것처럼 기존 시스템에서 (머신러닝, HMM-STATE, Kaldi 등) 몇 주 정도 걸리는 시간을 이 논문에서는 몇 시간 만에 다시 조정할 수 있었다고 한다.


기존의 TTS 시스템에서 [재교육]은 며칠에서 몇 주까지의 튜닝이 필요하지만 Deep Voice를 사용하면 몇 시간만에 모델 훈련을 끝내어 서비스가 가능하다.


3. 최신 기술에 비해 매우 빠르다.

이 논문의 저자는 인간이 말하는 것과 같은 오디오 합성에 관한 DeepMind의 주요 논문 인 WaveNet보다 400 배 빠른 속도를 달성한다고 주장하였다. 특히 그들은 다음과 밝혔는데,


프로덕션 준비 시스템을 만드는 데 중점을두기 때문에 evaluation을 위해 모델을 실시간으로 실행해야 했었다. Deep Voice는 1 초 단위로 오디오를 합성 할 수 있으며 합성 속도와 오디오 품질간에 조정 가능한 균형을 제공할 수 있다. 반대로 WaveNet의 이전 결과는 1 초의 오디오를 합성하는 데 몇 분의 런타임이 필요하다. (그러므로 우리 것이 훨씬 빠르다.)


먼저 Deep Voice가 어떻게 문장의 예를 들어 높은 수준에서 음성으로 변환하는지 살펴 보겠다. 이것을 추론 파이프 라인이라고 한다.


추론 파이프 라인 — 새로운 텍스트를 음성으로 변환

이제 Deep Voice에서 간단한 문장을 가져 와서들을 수있는 오디오로 변환하는 방법을 개략적으로 살펴 보겠다. 파이프 라인은 다음과 같이 아키텍처를 갖는다.

The inference pipeline of Deep Voice. Source: https://arxiv.org/pdf/1702.07825.pdf


이제이 파이프 라인을 단계별로 살펴보고이 조각들이 무엇인지, 어떻게 결합되는지 이해해본다. 특히, 다음 문구를 추적하여 Deep Voice가 어떻게 처리되는지 확인한다. 

It was early spring.

1 단계 : 그래 핀 (텍스트)을 음소로 변환

영어와 같은 언어는 음성이 아닌 점에서 독특하다. 예를 들어, 아래를 확인해보자.

1. though (like o in go)

2. through (like oo in too)

3. cough (like off in offer)

4. rough (like uff in suffer)


철자가 같은데도 발음이 어떻게 다른지 주목해야 된다. 바이두의 TTS 시스템이 철자를 주 입력으로 사용했다면,“though”와 “rough”가 같은 접미사를 갖지만 왜 그렇게 다르게 발음해야 하는지를 조정하려는 문제가 불가피하게 발생한다. 따라서 발음에 대한 자세한 정보를 나타내는 약간 다른 단어 표현을 사용해야한다. 

이것이 바로 음소 (phoneme)이다. 음소는 우리가 만드는 소리의 다른 단위이다. 그것들을 함께 사용하면 거의 모든 단어에 대한 발음을 재현 할 수 있다. 다음은 CMU의 음소 사전에서 수정 된 음소로 분리 된 단어의 몇 가지 예다.

  • White Room — [W, AY1, T, ., R, UW1, M, .]
  • Crossroads — [K, R, AO1, S, R, OW2, D, Z, .]


음소 옆에있는 1, 2 등의 숫자는 발음의 스트레스가 있어야하는 위치를 나타내며, 또한 마침표는 발음에서 빈 공간을 나타낸다. (Slience, End 부분)

따라서 Deep Voice의 첫 단계는 이와 같은 간단한 음소 사전을 사용하여 모든 문장을 음소 표현으로 간단히 변환하는 것이다. 즉 이러한 작업을, Grapheme to Phoneme (G2P) 라고 부른다.


예를 들어, 첫 번째 단계에서 Deep Voice에는 다음과 같은 입력 및 출력이 있다.

  • Input - “It was early spring”
  • Output - [IH1, T, ., W, AA1, Z, ., ER1, L, IY0, ., S, P, R, IH1, NG, .]


Step 2, Part 1: Duration Prediction

음소가 생겼으니, 말하면서이 음소를 얼마나 오래 참 아야하는지 추정해야한다. 음소가 문맥에 따라 더 길고 짧게 유지되어야하기 때문에 이것은 다시 흥미로운 문제이다. 음소“AH N”을 둘러싼 다음 예제를 보자.

  • Unforgettable
  • Fun


명백히“AH N”은 첫 번째 경우보다 두 번째 경우보다 훨씬 길어야하며,이를 위해 시스템을 훈련시킬 수 있다. 특히, 바이두는 각각의 음소를 취하여 얼마나 오래 (초) 보유 할 것인지 예측한다. 이 단계에서 예제 문장은 다음과 같다.


  • Input - [IH1, T, ., W, AA1, Z, ., ER1, L, IY0, ., S, P, R, IH1, NG, .]
  • Output - [IH1 (0.1s), T (0.05s), . (0.01s), … ]

Step 2, Part 2: Fundamental Frequency Prediction

The fundamental frequency (the blue line) is the lowest frequency the vocal cords produce during the voiced phoneme (think of it as the shape of the waveform). We’ll aim to predict this for each phoneme.

또한 각 음소의 톤과 억양을 예측하여 가능한 한 사람이 들리도록 만들려고 한다. 여러 가지면에서 이것은 동일한 사운드가 톤과 악센트에 따라 완전히 다른 의미를 가질 수 있는 만다린(중국)과 같은 언어에서 특히 중요하다. 각 음소의 기본 주파수를 예측할 수 있다면, 이 작업을 수행하는 데 도움이 된다. 주파수는 시스템이 음소가 발음 되어야 하는 대략적인 피치 또는 톤을 정확하게 알려주는 기능을 한다.

또한 일부 음소는 전혀 소리가 나지 않는데, 이것은 성대의 진동없이 발음 된다는 것을 의미한다. 예를 들어, 소리 "ssss"및 "zzzz"를 말하고 전자가 성대에서 진동을 일으키지 않는 경우 (음성 없음) 가 존재한다.

기본 주파수 예측은 이것을 고려하여 음소가 언제 울려야 하는지 그리고 그렇지 않아야 하는지를 예측한다.


이 단계에서 예제 문장은 다음과 같다.

  • Input - [IH1, T, ., W, AA1, Z, ., ER1, L, IY0, ., S, P, R, IH1, NG, .]
  • Output - [IH1 (140hz), T (142hz), . (Not voiced), …]

Step 3: Audio Synthesis

In the final step, we’ll combine phonemes, durations, and the fundamental frequencies (fO profile) to create real audio.

음성을 만드는 마지막 단계는 음소, 지속 시간 및 주파수를 결합하여 사운드를 출력하는 것이다. Deep Voice는 수정 된 버전의 DeepMind WaveNet을 사용하여 이 단계를 수행하였다. WaveNet의 기본 아키텍처를 이해하려면 해당 논문을 찾아보자. Autoregressive한 vocoder의 역할을 맡고 있다.

The original WaveNet from DeepMind can have exponentially many different inputs contribute to a single input. Notice the exponential tree structure outlined above. Source: https://deepmind.com/blog/wavenet-generative-model-raw-audio/

높은 수준에서 WaveNet은 raw audio를 생성하여 다양한 악센트, 감정, 호흡 및 기타 인간의 말의 기본 부분을 포함한 모든 유형의 사운드를 생성 할 수 있다. 또한 WaveNet은 이 한 단계 더 나아가 음악을 생성 할 수도 있다.


이 논문에서, Baidu 팀은 특히 고주파 입력을 위해 구현을 최적화하여 WaveNet을 수정하였다. 따라서 WaveNet에서 새로운 오디오를 생성하는데 몇 분이 걸리는 경우 Baidu의 수정 된 WaveNet은 Deep Voice의 저자가 설명하는 것처럼 1 초도 채 걸리지 않을 수 있다고 주장한다.

Deep Voice는 1 초 단위로 오디오를 합성 할 수 있으며 합성 속도와 오디오 품질간에 조정 가능한 균형을 제공한다. (하지만 블랙박스겠지...) 반대로 WaveNet의 이전 결과는 1 초의 오디오를 합성하는 데 몇 분의 시간이 소요될 수 밖에 없다.


Summary

이 3 단계를 통해 Deep Voice가 간단한 텍스트를 가져 와서 오디오 표현을 발견하는 방법을 살펴보았다. 단계를 한 번 더 요약하면 다음과 같다.


  1. 텍스트를 음소로 변환 (G2P 이용) “It was early spring”
  • [IH1, T, ., W, AA1, Z, ., ER1, L, IY0, ., S, P, R, IH1, NG, .]

2. 각 음소의 지속 시간과 빈도 예측

  • [IH1, T, ., W, AA1, Z, ., ER1, L, IY0, ., S, P, R, IH1, NG, .] -> [IH1 (140hz, 0.5s), T (142hz, 0.1s), . (Not voiced, 0.2s), W (140hz, 0.3s),…]

3. 음소, 지속 시간 및 주파수를 결합하여 텍스트를 나타내는 음파 출력

  • [IH1 (140hz, 0.5s), T (142hz, 0.1s), . (Not voiced, 0.2s), W (140hz, 0.3s),…] -> Audio



728x90
728x90

CUDA (Computed Unified Device Architecture)는 NVIDIA에서 개발한 GPU 개발 툴이다. 사실 CUDA는 c, c++기반으로 짜여진 완전 기초적 H/W 접근을 해야하는데, 많은 연구자들이 딥러닝에 사용할 수 있도록, 쉽게 설치할 수 있도록 오픈하였다. 현재는 nvidia-driver, CUDA, CUDNN만 설치하면 딥러닝을 쉽게 사용할 수 있다. 


CUDA를 사용하는 이유는 매우 간단한데, 많은 양의 연산을 동시에 처리하는 것이 목표이다. 그러므로 딥러닝, 채굴과 같은 수학적 계산에 많이 쓰인다. 미분은 컴퓨터로 가능하기 때문이다.


기존의 컴퓨터 연산은 CPU를 사용하고, RAM에 의존하여 연산을 진행하였다. CPU를 이용한 연산은 대부분 Single-Core(Human-Brain)를 사용하고 MultiProcessing, Multi-Threading 등을 이용하여 CPU가 보유한 코어 갯수 만큼의 Multi-Core를 이용하여 연산을 할 수 있다. 일반적으로 딥러닝에서 사용하는, 특히 pytorch나 tensorflow 에서, data loader 파트에서, core 갯수를 주고 데이터 loading 하는 부분이 여기에 속한다.



이에 반해 GPU는 Core 갯수가 엄청나다. CPU는 8~16개인데 비해 GPU는 몇 천개 이상이다. 즉 이를 이용한 Many-Core dependent 연산을 진행하고, Video RAM에 있는 데이터를 연산한다.


각 각의 Core 별 속도는 CPU가 GPU보다 훨신 빠르다. CPU의 코어 당 속도가 3.0 GHz 정도이다. GPU 같은 경우, 16년 하반기에 등장한 Pascal Architecture 의 경우 1.8 GHz 로 많이 증가했으나 이전 Maxwell 2th Architecture에서의 속도는 0.9GHz 정도였다. 그렇지만 코어의 숫자는 이 때 당시의 CPU의 경우 집에서 게임하거나 사무용으로 쓰이는 평균의 개수는 4코어, GPU는 1500 코어 이상이었다.



많은 연구자들이 사용하는 python, matlab 같은 경우 행렬 연산을 사용할 수 밖에 없다. 이 때 쓰이는 것이 재귀연산 (recursive 연산)인데, 이 함수는 '직렬' 연산을 해야한다. 하지만 이런 경우가 아니고 단순 계산, 예를 들어 backpropagation을 진행하며 보는 미적분 같은 경우 병렬 연산을 해주는 것이 훨씬 효과적이다. 

행렬 연산



위의 경우 (4,4) 행렬이다. 연산이 더 빠른 직렬 연산의 경우에 대해 살펴보겠다. (1,1) 위치에 더해질 숫자 (1)를 입력 후 행/열 순으로 증가하며 previously adding 된 각 행에 더한다고 하면, (1,1) 위치의 덧셈 이후 (2,1)의 덧셈을 진행할 때 마찬가지로 이전에 더했던 값을 알아야 된다. 그러므로 연산이 순차적으로 진행되어야 한다. 이런 경우에는 병렬 연산에는 적합하지 않고, 단일 코어의 속도가 높은 CPU를 이용한 연산이 더 유리하다,


(4,4)행렬 모든 성분에 만약 1의 값을 더한다는 연산 process에 대해 논해보자. 직렬 연산의 경우 이 연산을 16번 (4,4 행렬이므로) 해야 끝나지만, 병렬 연산의 경우 16번의 연산을 병렬인 한 번에 처리한다. 즉 같은 값을 더해 주기 때문이다. 


앞서 언급한 CPU와 GPU의 코어 수, 속도로 살펴보았을 때, 코어 당 속도가 CPU가 GPU의 2배라고 가정하자. 이럴 경우 CPU로 연산하면 8의 시간이 걸린다고 하였을 경우(0.5 x 16), GPU를 이용하면 1의 시간이 걸린다. (1 x 1)


아래의 영상을 보면, NVIDIA에서 제공해주는 CPU와 GPU의 비교 영상이다.

NVIDIA에서 공개한 GPU vs CPU



https://youtu.be/-P28LKWTzrI

728x90
728x90

CUDA 병렬 프로그래밍 CUDA 병렬 처리

최근 GPGPU를 이야기함에 있어서 빠지지 않고 등장하는

CUDA에 대해서 알아보자

집에서 또는 연구실에서 사용하고 있는 Desk Top 컴퓨터에 그래픽 카드 한 장을 추가함으로 인해서 계산 및 Simulation 속도가 200배가 빨라 진다면 과연 사람들은 이 기술을 어떻게 받아 들일까?

엔비디아는 CUDA(Compute Unified Device Architecture)라는 기술을 2006 10월 웹에서 공개하면서 본격적으로 개인용 슈퍼 컴퓨터의 시대를 열어가려고 하고 있다.

오늘날의 GPU High Performance Computing(HPC)에 있어서 가장 적합한 솔루션이라고 평가되고 있으며 세상에서 가장 빠르게 확산이 되고 있는 기술 중에 하나이다특히 학술계산 분야에 있어서의 Heterogeneous Computing을 통해 시스템을 최적화함으로써 CPU Operating System, Task 처리와 같은 순차적인 업무를 위주로, GPU Massive Data를 처리하게 된다. GPU CPU대비 10배 가까운 메모리 인터페이스 Speed 240개의 Core에서 동시에 Data를 처리함으로써 최대 200배 이상까지도 계산 속도를 높일 수 있으며 또한 시스템을 최적화 시킬 수 있다.

 

CUDA ("Compute Unified Device Architecture", 쿠다)는

그래픽 처리 장치(GPU)에서 수행하는 (병렬 처리) 알고리즘을 C 프로그래밍 언어를 비롯한 산업 표준 언어를 사용하여 작성할 수 있도록 하는 GPGPU 기술이다.

CUDA는 엔비디아가 개발해오고 있으며 이 아키텍처를 사용하려면 엔비디아 GPU와 특별한 스트림 처리 드라이버가 필요하다. CUDA는 G8X GPU로 구성된 지포스 8 시리즈급 이상에서 동작한다. CUDA는 CUDA GPU 안의 명령셋과 대용량 병렬 처리 메모리를 접근할 수 있도록 해 준다.

개발자는 패스스케일 오픈64 C 컴파일러로 컴파일 된 '쿠다를 위한 C' (C언어를 엔비디아가 확장한 것) 를 사용하여 GPU 상에서 실행시킬 알고리듬을 작성할 수 있다.

 

쿠다 구조의 계산 인터페이스

쿠다 구조는 일련의 계산 인터페이스를 지원하며 이에는 OpenCL, DirectX Compute가 포함된다. C 언어가 아닌 다른 프로그래밍언어에서의 개발을 위한 래퍼(Wrapper)도 있는데, 현재 파이썬포트란자바와 매트랩 등을 위한 것들이 있다.

 

쿠다의 전망

쿠다를 통해 개발자들은 쿠다 GPU 안 병렬 계산 요소 고유의 명령어 집합과 메모리에 접근할 수 있다. 쿠다를 사용하여 최신 엔비디아 GPU를 효과적으로 개방적으로 사용할 수 있다. 그러나 CPU와는 달리 GPU는 병렬 다수 코어 구조를 가지고 있고, 각 코어는 수천 스레드를 동시에 실행시킬 수 있다. 응용 프로그램이 수행하는 작업(계산)이 이러한 병렬처리연산에 적합할 경우, GPU를 이용함으로써 커다란 성능 향상을 기대할 수 있다.

 

쿠다 적용

컴퓨터 게임 업계에서는 그래픽 랜더링에 덧붙여, 그래픽 카드를 게임 물리 계산 (파편, 연기, 불, 유체 등 물리 효과)에 사용된다.

쿠다는 그래픽이 아닌 응용 프로그램, 즉, 계산 생물학, 암호학, 그리고 다른 분야에서 10배 또는 그 이상의 속도 혜택을 가져왔다. 이 한 예는 BOINC 분산 계산 클라이언트 이다.

쿠다는 저수준 API와 고수준 API 모두를 제공한다. 최초의 CUDA SDK는 2007년 2월 15일에 공개되었으며 마이크로소프트 윈도와 리눅스를 지원했다. 맥 OS X지원은 2.0 버전에 추가되었다.

 

 

쿠다의 장점

1. 흩뿌린 읽기 - 코드가 메모리의 임의 위치에서 데이터를 읽을 수 있다.

2. 공유 메모리 - 쿠다는 고속 공유 메모리 지역 (16 또는 48KB 크기) 을 드러내어 스레드 간에 나눌 수 있게 해 준다. 이는 사용자 관리 캐시로 사용될 수 있는데, 텍스처 룩업을 이용하는 경우 보다 더 빠른 대역폭이 가능해진다.

3. 디바이스 상의 읽기, 쓰기가 호스트보다 더 빠르다.

4. 정수와 비트 단위 연산을 충분히 지원한다. 정수 텍스처 룩업이 포함된다.

 

쿠다의 예

 

 

 

 

 

쿠다의 제한

  • 재귀호출, 함수 포인터가 없는 C 언어의 하부 집합을 확장하여 사용한다. 그러나 한개의 처리 장치가 여러개의 쪼개진 메모리 공간에 대하여 작업하여야 하는 점이 다른 C 언어 실행 환경과 다른 점이다.
  • 텍스처 랜더링은 지원 되지 않는다.
  • 배정도에 관해서는 IEEE 754 표준과 다르지 않다. 단정도에서는 비정상값과 신호 NaN이 지원되지 않고, IEEE 반올림 모드 가운데서는 두가지만 지원하며, 이도 명령어에 따라서 지원되는 것으로 제어 단어(Control word)에서 지원 되는 것은 아니다.(이것이 제한점인지는 논란의 대상이 될 수 있다) 그리고 나눗셈과 제곱근의 정밀도가 단정도에 비해 조금 낮다.
  • CPU와 GPU 사이의 버스 대역폭과 시간 지연에서 병목이 발생할 수 있다.
  • 스레드가 최소한 32개씩 모여서 실행되어야 최선의 성능 향상을 얻을 수 있으며, 스레드 수의 합이 수천개가 되어야 한다. 프로그램 코드에서의 분기는, 각각의 32 스레드가 같은 실행 경로를 따른다면, 성능에 큰 지장을 주지 않는다. SIMD 실행 모델은 어떠한 내재적으로 분기하는 임무에게는 심각한 제한이 된다. (예를 들어, 광선 추적 가속 자료 구조)
  • 쿠다 기반 GPU는 엔비디아에서만 나온다.
  •  

     

    CPU와 GPU의 개념적 차이

     

     

    CUDA 컴파일 환경

     

    컴파일 워크플로우

    nvidia CUDA

    기존의 개발환경에서는 GPGPU를 위해서 C/C++에서 그래픽 하드웨어를 컨트롤 하기 위해 Cg, DirectX, OpenGL 등의 쉐이더 명령어를 사용해야 한다이러한 방법의 단점은 그래픽에 대한 API의 복잡성으로 인하여 쉽게 프로그래밍 하기 어렵다는 단점이 있다. CUDA는 이러한 단점을 해결하기 위한 방법인데이를 위해 좀더 쉬운 명령어 셋을 C언어에 추가하고추가된 명령어는 NVCC를 통해 GPU컨트롤이 가능한 Assemble 코드인 PTX Assemble 코드로 변환하여 사용할 수 있도록 한다.

     

    이러한 과정은 복잡해 보일 수 있는데, C언어 기반의 기존 컴파일러와 CUDA 명령어를 컴파일 할 수 있는 NVCC 컴파일러 두 개가 각 시스템에 맞는 오브젝트 파일이 만들어지고최종 결과물은 하나의 실행파일이 만들어 진다여기서 cudafe CUDA Front End의 약자로 사용되었다.

     

     

     

    CUDA C/C++에 확장된 명령어 셋이다표준 C/C++ 이외의 CUDA만의 Syntax가 존재하는데이는 기존 C Compiler에서는 작동하지 않고 NVCC에서만 인식하여 컴파일하게 된다명령어 확장 셋으로는 크게 4가지로 나뉘는데, Kernel 실행 시 사용되는 Triple Bracket, 함수 관리 선행어메모리 관리 선행어, CUDA 내장 구조체와 변수들이다.

     

     

    CUDA 병렬처리의 간단한 샘플

     

     

     

    #include <stdio.h>

    __global__ void arrtest(int *d_a)
    {
     int a;
     int b;
     int i=blockIdx.x * blockDim.x + threadIdx.x;
     int j=blockIdx.y * blockDim.y + threadIdx.y;
     int test[25]={5,5,2,6,3,
        3,5,2,4,4,
        1,3,5,2,3,
        3,4,2,3,1,
        5,2,3,2,1};
     int test1[25]={1,2,1,2,1,
        2,1,2,1,2,
        1,2,1,2,1,
        2,1,2,1,2,
        1,2,1,2,1};

     for(a=0;a<5;a++)
     {
      b+=test[j*5+a]*test1[i*5+a];
     }
     d_a[i*5+j]=b;
    }
    int main(int argc, char** argv)
    {
     int i;
     int *d_a;
     int *h_a;
     int test[25]={1,2,1,2,3,1,2,3,2,1,1,2,3,1,2,3,2,2,1,2,1,2,3,2,3};

     size_t memsize=5*5*sizeof(int);
     h_a=(int *)malloc(memsize);
     cudaMalloc((void **)&d_a, memsize);

     for(i=0;i<25;i++)
      h_a[i]=test[i];
     /**h_a=*test;*/

     dim3 dimgrid(1,1);
     dim3 dimblock(5,5);
     cudaMemcpy(d_a, h_a, memsize, cudaMemcpyHostToDevice);
     arrtest<<<dimgrid,dimblock>>>(d_a);
     cudaMemcpy(h_a, d_a, memsize, cudaMemcpyDeviceToHost);
     
     for(i=0;i<25;i++)
      printf("%d ",h_a[i]);
     printf("\n");

     scanf("%d ",&i);

     cudaFree(d_a);
     free(h_a);

     

     

     

    CUDA Documents

    http://docs.nvidia.com/cuda/index.html

     

    CUDA Toolkit

    https://developer.nvidia.com/cuda-toolkit-31-downloads

     

     

    CUDA 관련 영상

     

     

     

     

     

     

     

    [출처] CUDA 병렬 프로그래밍|작성자 치국바보

    www.miruware.com

    위키피디아

    youtube 


    728x90
    728x90

    웨이블릿은 벡터의 0값을 중심으로, 매 번 변화하는 진폭을 보유한 파형이라고 볼 수 있다. 

     

     
    즉, 진폭이 0에서 시작하여 증가한 다음, 다시 0으로 감소하는 물결 모양의 진동이다. 일반적으로 웨이블릿은 신호 처리에 유용한 특정 속성을 갖도록 제작되었다. 또한 Convolution을 사용하여 wavelet을 손상된 신호의 알려진 부분과 결합하여 unseen 부분에서 정보를 예측 및 추출 할 수 있다.


    웨이블릿 변환은 완전히 다른 성능 함수를 가진 푸리에 변환 (또는 푸리에 변환과 훨씬 유사)과 유사하다. 주요 차이점으로, 푸리에 변환은 신호를 사인과 코사인, 즉 푸리에 공간에 국한된 함수로 분해하는데 반해 웨이블릿 변환은 실제 공간과 푸리에 공간 모두에 국한된 함수를 사용한다. 일반적으로 웨이블릿 변환은 다음 방정식으로 표현할 수 있다.


    여기서 *는 복합 켤레 기호이고 함수 ψ는 일부 함수이며, 이 기능은 특정 규칙을 준수하는 경우 임의로 선택될 수 있다. 위에서 볼 수 있듯이, 웨이블릿 변환은 실제로 계산에 사용 된 성능 함수에 따라 다양한 변환이 가능한 세트로 볼 수 있다.

    위와 같은 이유로, 매우 다른 상황과 응용 공간에서 웨이블릿 변환이라는 용어를 들을 수 있는 주된 이유이다.  웨이블릿 변환 유형을 정렬하는 방법에는 여러 가지가 있는데, 여기에서는 웨이블릿 직교성을 기반으로 한 분할만 설명한다.
     
    이산 웨이블릿 변환 개발에 직교 웨이블릿을 사용하고 연속 웨이블릿 변환 개발에 비 직교 웨이블릿을 사용할 수 있다. 이 두 변환에는 다음과 같은 속성이 있는데,

    1. 이산 웨이블릿 변환은 입력 길이와 동일한 길이의 데이터 벡터를 반환한다. 일반적으로 이 벡터에서 대부분의 데이터는 (element 값들) 거의 0이다. 이는 변환 및 스케일링에 직교하는 wavelet 세트(함수)로 분해 된다는 사실에 해당한다. 그러므로 그러한 신호를 신호 데이터 포인트의 수와 동일하거나 더 적은 수의 웨이블릿 계수 스펙트럼으로 분해해야 한다. 이러한 웨이블릿 스펙트럼의 장점 중 하나는, 중복 정보가 없기 때문에 신호 처리 및 압축에 매우 좋은 편이다.


    2. 반대로 연속 웨이블릿 변환은 입력 데이터보다 차원이 1개가 더 큰 배열을 반환한다. 1D 데이터의 경우 시간-주파수 평면의 이미지를 얻는다. 신호의 지속 시간 동안 신호 주파수의 변화를 쉽게보고 스펙트럼을 다른 신호 스펙트럼과 비교할 수 있다. 이 때, 비직교형 웨이블릿 세트를 사용함에 따라 데이터는 서로 밀접하게 관련되어 있기 때문에 여기에서 큰 중복성을 찾을 수 있다. 이를 통해보다 좋은 형태로 결과를 볼 수 있다.

     

    728x90
    728x90

    원문: http://cafe.naver.com/rapid7/2285


    딥러닝 기반의 음성인식 기술


     

    음성인식 기술의 개요


    음성은 사람 간의 가장 자연스러운 의사소통 방식이다. 음성 인식 기술은 이미 스마트폰, 자동차, 콜센터 등 현재 우리 생활 의 많은 부분에 녹아들어서 서비스화되고 있다.

    음성인식 기술은 사람이 일상생활에서 발성한 모든 내용을 그대로 받아 적으며(dictation), 외국인이 자기 나라 언어로 발 성한 것을 그대로 우리말로 통역해 주거나 그 반대로 해 주는 자동통역(automatic interpretation), 원어민과 대화하듯이 영어 회화를 가르쳐 주는 컴퓨터 언어교사(language tutor), 말만하면 알아서 일정관리 및 대화상대 등을 해주는 지능형 비 서 등의 개발을 궁극의 목표로 한다.

    과거 음성인식의 역할 은 소리를 문자로 바꾸 어주는 것에 한정되어 있었으나 현재는 사람과 기계간의 대화를 가능하 게 하는 자연어처리 (natural language processing) 기술까지도 그 기술적 영역 안에 포 함하기도 한다. 따라서 인공지능의 한 세부 영 역으로써 음성인식 기술 을 포괄적으로 언어지능 으로 분류하기도 한다.

    인공지능 기술이 1950년대에 태동(Birth)해 1990년대에 암 흑기(Winter)를 맞았던 것과 유사하게, 음성인식도 약 50여년 동안 발전을 거듭해 오면서 암흑기를 겪기도 했다. 음성인식 기술이 몇 차례 그 기술적 부침을 겪어가면서 오늘날 비교적 똑똑한 모습으로 우리 생활 가까이에 다가오고 있는 배경에는 하드웨어의 비약적 발전이 자리하고 있다.





    예를 들어 1950년대 RCA에서 개발된 음소타자기나 1960년 대에 개발된 숫자 음성 인식기는 규모나 계산 능력 면에서 수 백 배나 작은 스마트폰의 그것보다 훨씬 못 미치는 성능으로 훨씬 낮은 수준의 인식 대상만을 고려할 수 밖에 없었다.

    최근 몇 년 동안 딥러닝으로 말미암아 혁신적인 성능을 보이 고 있는 음성인식 기술도 보편화되고 있는 클라우드 서버 및 고성능 GPU와 같은 하드웨어의 눈부신 발전에 그 배경을 두 고 있다.

    아직 완전하다고는 할 수 없지만 음성인식 성공의 또 다른 측면에는 포기하지 않는 연구자들의 끊임없는 노력이 있었다 고 하겠다.

    예를 들어 최근 음성인식에 사용되는 주요한 딥러닝 기술 패 러다임들인 DNN(Deep Neural Networks), CNN(Convoluti on al Neural Network), LSTM-RNN(Long Short-Term Memory - Recurrent Neural Network)1) 등은 이미 1990년 대에 이론적, 개념적 토대가 완성됐지만 사장될 위기에 있었 다. 하지만 이를 실용적 성능으로 개선하기 위한 연구자들의 끊임없는 노력 덕분에 2000년 후반부터 빛을 보기 시작했는 데, 여기에 고성능 GPU와 같은 하드웨어의 지원에 편승하여 비로소 꽃을 피우게 됐다.

    음성인식 및 인공지능 기술 발전의 또 한가지 중요한 배경에 는 오픈소스에 기반하는 생태계의 활성화를 들 수 있다. 예를 들어 딥러닝과 관련된 오픈소스 기반의 도구들을 들 수 있다. Kaldi(미국의 존스홉킨스대학), Caffe(미국 버클리대학), Tensorflow(구글), Theano(캐나다 몬트리올대학), Torch(페 이스북), CNTK/DMTK(마이크로소프트), cuDNN(엔비디아) 등이 여기에 해당한다. 여기서 중요한 사실은 구글이나 페이스 북 등 글로벌 주요 IT 기업들이 자체적인 오픈소스 도구를 개 발할 뿐만 아니라 주요 대학에도 개발비를 지원하고 있다는 사 실이다.

    결국 주요 IT 기업의 투자가 대학이나 연구소의 연구자금으 로 투입되고, 연구자들은 안정적인 환경에서 연구개발을 함으 로써 중장기적으로 우수한 연구 인력 및 산출물을 기업에서 수 혜받게 되는 선순환 구조가 만들어지고 있다.

    한편, 음성인식 기술의 비약적 발전에도 불구하고 여전히 음 성인식은 사람들이 웅성거리는 식당, 회의실, 버스나 지하철 등과 같은 환경에서는 매우 낮은 정확도를 보이는 등 개선할 점이 많다. 다양한 잡음 요인을 고려하지 않더라도 이렇게 음 성인식이 어려운 이유는 먼저 동일한 사람인 경우에도 나이가 들어가거나 병적인 요인에 따라 목소리에 다양한 변이 요인이 발생하며, 동일한 단어라도 감정 및 사투리 등의 영향에 따라 사람마다 발성이 다르고, 문맥에 따라 발성이 달라진다는 점 때문이다.

    이러한 음성인식 기술은 기술적으로<표 1>과 같이 분류할 수 있다. 화자 종속에서 독립으로, 고립어에서 연속어로, 소용량 어휘에서 대용량 어휘로 갈수록 높은 난이도를 나타낸다. 이외 에도 음성인식 기술의 단점은 등록이 되지 않은 단어 또는 어 휘는 인식이 불가능하며 우리나 라처럼 지역에 따라 다양한 사투 리가 섞여있는 경우에도 인식이 어렵다. 특히 제주 방언 같은 경 우에는 아예 다른 언어로 취급될 정도로 어휘나 억양이 달라서 인 식이 거의 불가능할 수도 있다.




     


    딥러닝 기반의 음성인식 기술


    오늘날 일반적으로 사용되는 음성인식기의 기본 구조는 다음 과 같이 나타낼 수 있다.

    음성인식기는 크게 언어모델 과 음향모델이라는 2가지의 중 요한 지식원(knowledge source)을 사용해 음성 신호로부터 문자 정보를 출력하게 되는데, 이때 개념적으로 음성 신호를 문자 심볼로 해석한다는 차원에서 음성인식 알고리즘을 디코 더(decoder)라고 부르기도 한다.

    현재 일반적으로 사용되는 음향모델(acoustic model)은 우 리말의‘ㄱ’,‘ ㄴ’,‘ ㄷ’, …,‘ ㅏ’,‘ ㅑ’,‘ ㅓ’, …등의소리단 위를 딥러닝 기술로 학습해서 지식화해 놓고 디코더에서 사용 한다. 언어 모델은 단어나 어휘적 쓰임새를 학습해 지식으로 가지고 있는데 예를 들어‘아버지’라는 어휘 다음에‘는’, ‘이’,‘ 를’등과같은어휘가어느정도의확률로나타날수있 는 가를 나타내는 통계적 모델이 일반적으로 적용된다.





    이 외에 자음접변, 구개음화 등의 일반적인 음운 현상을 반 영하기 위해 발음규칙이 사용되며, 인식 어휘 자체를 등록하기 위해 어휘 사전이 사용된다. 현재 시점까지는 음향모델 측면에 서 딥러닝 기술이 매우 효과적이며 언어모델 측면에서는 그 효 과가 상대적으로 약하게 나타나고 있다.

    한편 종래의 음성인식 기술은 아나운서가 국어책을 읽듯이 발성하는 음성을 대상으로 하는 낭독체 음성인식 기술이 주로 연구대상이었으나, 딥러닝 및 잡음처리 기술의 발전으로 인해 현재는 사람간의 자연스런 대화 음성을 대상으로 기술 고도화 가 이루어지고 있다.

    대화체음성인식이어려운이유는‘그러니까’,‘ 음’,‘ 아참’ 등등 헤아릴 수 없이 많은 간투사가 수시로 사용되며, 더듬거 림, 어휘의 도치 현상, 동일 어휘의 반복이나 어휘적 단락(끊어 짐), 재발성 등등으로 인한 비문법적인 비정형 발성이 빈발함 에 기인하는데, 이를 통칭해서 비정형 자연어(unstructured spontaneous speech)라고로 정의하고 있다.

    직관적으로 봐도 기존의 어휘적 쓰임새를 통계적 지식에 의 존해서 처리해야 하는 메커니즘으로는 해결이 어렵기 때문에 새로운 방식의 언어 모델이 필연적으로 개발되어야 한다. 이러 한 통계적 방식의 단점을 극복하고 비정형=0 src="http://www.dbguide.net/publishing/img/knowledge/tech_img4360.jpg">

    한편 구글과 같이 수십만대의 서버를 동원해서 클라우드 기 반의 음성인식을 하는 경우에는 문제될 것이 없지만, 특정 기 업의 콜센터 또는 고객센터처럼 제한된 공간에서 제한된 수의 서버를 운용하는 경우 서버당 처리 가능한 고객의 수에 한계가 있을 수 밖에 없기 때문에 단일 컴퓨터 서버에서 몇 개까지의 음성인식 디코더가 실행될 수 있는지를 연구하는 것도 매우 중 요하다고 할 수 있다. 이를 위해 동시접속(concurrency) 성능 을 최대화하는 음성인식 디코더의 집적 및 최적화 기술도 중요 한 연구 요소 중의 하나이다.

    현재 다양한 수준의 빅데이터가 존재하고 활용이 가능하지 만 실질적으로는 여전히 데이터에 대한 갈증이 크다. 예를 들 어 특정 카드회사에서 누적된 사용자 경험(user experience) 은 유사한 업종인 보험회사에서조차 효과적으로 쓰이지 못할 수 있고, 의료 분야에서 일반적으로 사용되는 사용자 경험이 법률 분야에서는 사용 불가능할 수도 있는 것이다.

    이를 위해 기술적으로 언어 모델이나 음향 모델을 정규화하 거나 적응하도록 하는 학습 메커니즘을 동원하기도 한다. 이러 한 적응 및 정규화 방식은 여전히 전문가가 개입해야만 하는 한계가 있기 때문에, 다양한 영역의 데이터가 누적됨에 따라 스스로 학습해서 지식을 구축해 나가는 방향으로 딥러닝 기술 을 응용하기도 한다.

    즉, 향후에는 인간의 뇌처럼 스스로 학습하고 지식을 축적해 나가는 형태로 인공지능이 발전하게 된다는 것이다.

    다음 그림은 전통적인 은닉마르코프 모델 기반의 음성인식 기술(HMM; Hidden Markov Model)과 딥러닝 기반의 음성인 식 기술(DNN; Deep Neural Network)2)을 방송대담 프로그 램, 학술 발표 및 학술 토론 데이터를 대상으로 성능 평가한 결 과이다. HMM’14는 기본 성능, HMM’15는 잡음처리 및 고성 능 음향 모델을 적용한 성능, DNN’15는 딥러닝 기반의 음성인 식 기술의 성능을 보이고 있는데, 고도의 잡음처리 기술을 적 용한 것보다 딥러닝 기술을 적용하는 쪽이 보다 우수한 성능을 보임을 상징적으로 보여주고 있다.




     


    딥러닝과 음성인식의 미래


    딥러닝과 음성인식을 포함하는 인공지능 기술의 미래를 현 재와 비교해 보면 다음과 같이 예상해 볼 수 있을 것이다. 현재 시점에서 딥러닝을 포함하는 대표적인 인공지능 기술 로 IBM의 TrueNorth3), 구글의 딥마인드4)5), IBM의 Watson6) 등을 들 수 있다.



    학습의 기본 알고리즘 측면에서는 영상, 문자, 음성, 제스처 등 단일한 모달리티(modality)를 독립적으로 학습 및 인식하 는 방식에서 나아가 영상이나 음성 등의 여러 가지 모달리티를 동시에 학습 및 인식하는 방식으로 변화할 것이 다. 예를 들어, 음성 신호와 입술의 움직임을 동시 에 사용해서 고성능 음성인식이 가능하게 되는 것 이다.

    다음으로 시간적으로나 공간적으로 분리된 대 상(object)을 인식하는 이산형(discrete), 분절형 (segmented) 방법론으로부터 이들을 시간적, 공 간적으로 연동해 학습함으로써 인식 성능을 높이 는 방향으로 발전하게 될 것이다. 예를 들어 단순 한 정지 영상 또는 그 결합을 인식 대상으로 하지 않고 연속된 영상 자체를 인식하는 동적/증강형 (dynamic/incremental) 학습으로 발전하게 될 것이다.





    또한 단순 데이터나 패턴을 분류하는 데서 나아가 대상이 내포하는 의미까지 인지하게 되는 방향으로 발전하게 될 것이 다. 예를 들어 음성 신호에서 특정 어휘를 인식한 다음 단어가 문맥적으로 어떤 의미를 내포하고 있는지, 어떠한 감정이 포 함되어 있는지 까지 파악하여 대화를 진행할 수 있게 될 것이 다. IBM 왓슨(Watson)과 같은 지식학습 인공지능은 전통적 인 규칙 및 통계 기반의 인공지능 시스템으로 정의된다. 최근 IBM에서도 인지컴퓨팅(cognitive computing)과 같은 기술 패러다임을 집중적으로 연구하고 있기는 하지만 여전히 방대 한 지식은 전문가의 정교한 손끝에서 생성된다.

    향후 이러한 수동 또는 반자동으로 생성되는 지식은 데이터 만 주어지면 인공지능이 스스로 학습해서 지식을 쌓아가는 형 태인 자율 학습 방법론에 따라 사람의 개입이 최소화되는 방 향으로 발전할 전망이다.

    또한, 하나의 지식이 생성되면 유사한 지식을 자가적으로 확장해 나가는 다중도메인 확장 지식, 다양한 지식을 검색하 고 분석하는 방식에서 나아가 기존 지식에 기반해서 새로운 사실을 예측해 나가는 예측형 지능으로 발전할 전망이다.

    현재 사람 두뇌를 모방한 물리적인 프로세서 중 가장 앞선 기술로는 IBM의 TrueNorth를 들 수 있다. 하지만 여전히 100만 개의 뉴런을 동원해서 5개 정도의 패턴을 80%를 상회 하는 인식 정확도로 인지가 가능하다.

    아직은 기능적 한계와 낮은 효율성을 보이고 있지만 조만간 연구자들에 의해 실용적 성능의 프로세서가 개발될 것으로 전 망된다.




     


    맺음말


    음성인식 기술이 최근 비약적인 성능 향상을 이루면서 우리 실생활에 스며들고는 있지만 여전히 영화‘스타워즈(Star Wars)’나‘그녀(Her)’에서 나오는 이상적인 기술과는 많은 차이가 있다.

    하지만 음성인식을 포함하는 언어지능 기술은 타 산업의 제 품과 서비스에 공통적으로 적용되는 기반 기술이며, IT와 전 통산업의 효과적인 융합을 위한 핵심 원천 기술로써 지속적으 로 연구되어야 하는 중요한 인간-컴퓨터 상호작용(Human- Computer Interaction) 기술의 하나인 것은 분명하다. 이러 한 측면에서 딥러닝과 같은 알고리즘적 혁신, GPU와 같은 물 리적 하드웨어적 혁신은 지속되어야 하며 이를 통해 인류는 보다 나은 미래를 맞이할 수 있을 것이다



    출처 : DBguide.net



    728x90
    728x90

    * Rundll 커맨드 라인

    RUNDLL.EXE <DLL 명>,<엔트리 포인트> <옵션 아규먼트>


    를 이용하여 실행


    .lnk (참조 되어 있는 샘플 파일) 의 커맨드라인 분석, 복사


    그 후 rundll32.exe와 해당 .dll파일 주소를 샘플 파일과 같이 이동,


    ex: C:\Windows\SysWOW64\rundll32.exe C:\Windows\SysWOW64\cb3cacb2418b31f93e8172d12c00fef8bb1bbf0b222f5d2afcf876219926e86b.dll,MXS3



    728x90
    728x90
    요약
    윈도우 95는 DLL에서 익스포트된 함수를 실행하는 16비트, 32비트 Rundll.exe과 Rundll32.exe 커맨드-라인 유틸리티를 가진다. 그러나, Rundll과 Rundll32 프로그램이 모든 DLL로 부터의 모든 익스포트 함수에 대해 실행되지는 않는다. 예를 들어 시스템 DLL에서 익스포트되는 Win32 API (Application Programming Interface) 는 콜할 수없다. 작성한 DLL에 존재하는 익스포트 함수에 대하여만 가능하다. 여기에서는 윈도우 NT와 95하에서 Rundll과 Rundll32 사용법을 다룬다. 원래 Rundll과 Rundll32 유틸리티는 마이크로소프트 내부용의로 설계되었다. 그러나 그 기능이 일반적이므로 현재는 공개되었다. 
    주 : 윈도우 NT 4.0은 Rundll32만 포함되며 Rundll32만 지원한다.
    추가 정보

    * Rundll 과 Rundll32 비교

    Rundll은16-비트 DLL을 로드하고 실행하며, 반면 Rundll32는32-비트 DLL을 로드하고 실행한다. 잘못된 DLL을 Rundll 나 Rundll32에 사용하는 경우, 오류 메시지 없이 실행에 실패한다.

    * Rundll 커맨드 라인

    RUNDLL.EXE <DLL 명>,<엔트리 포인트> <옵션 아규먼트>
    다음은 예이다:
    RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF
    다음은 위 명령어 라인에서 주의해야한 3가지 문제이다:
    1. Rundll 이나 Rundll32은 주어진 DLL 파일명을 LoadLibrary() 함수가 사용하는 표준위치에서 찾는다. 정확을 기하기 위해서는 DLL의 풀-패스를 기술하고, 유효한 파일명이 되기 위해서는 긴 파일명 대신 짧은 파일 명을 기술한다. 즉 "C:\Program Files" 폴더는 반드시 짧은 폴더 명으로 변환되어야 한다.
    2. <DLL 명>에는 스페이스, 콤마, 따옴표등이 포함될 수없다. 이것은 Rundll 커맨드 분석기의 한계이다.
    3. 위 커맨드 라인에서, <DLL 명>과 <엔트리 포인트>사이의 컴마(,)는 매우 중요하다. 만약 컴마가 없다면, Rundll이나 Rundll32는 어떤 오류 메시지 없이 실패한다. 또한 <DLL 명>, 컴마와 <엔트리 포인트> 함수 사이에는 스페이스도 없어야만 한다.

    * Rundll 동작 방법

    1. 커맨드 라인을 분석한다.
    2. LoadLibrary()로 명시된 DLL을 로드한다.
    3. GetProcAddress()로 <엔트리 포인트> 함수의 어드레스를 얻는다.
    4. <옵션 아규먼트>를 <엔트리 포인트> 함수로 패스하면서 콜한다.
    5. <엔트리 포인트> 함수 리턴시 Rundll.exe는 DLL을 언로드하고 종료한다.

    * DLL 작성법

    작성하는 DLL에서, 다음같은 함수 원형 <엔트리 포인트> 함수를 만든다:


    16-비트 DLL:

    void FAR PASCAL __loadds
    EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);

    32-비트 DLL:

    void CALLBACK
    EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
    엔트리 포인트 함수는 다음을 고려해야 한다.
    1. "EntryPoint"는 반드시 실제 엔트리 포인트 함수명 이어야 한다. Rundll32의 엔트리 포인트는 프로세스와 쓰레드 어태치/디태치 통보(notifications)를 처리하는 32비트 DLL의 DllEntryPoint함수와 완전히 별개이다.
    2. Rundll32의 엔트리 포인트 함수는 반드시 _stdcall(CALLBACK은 디폴트로 _stdcall 속성을 사용한다)을 정의해야만 한다. 만약 _stdcall이 없으면, 함수는 디폴트로 _cdecl를 사용하며, 이때 Rundll32은 함수 호출 후, 비정상적으로 종료한다.
    3. 반드시 함수 선언에 _stdcall 를 사용해야 하며, 비주얼 C++ 컴파일러는 DLL이 C로 쓰여진 경우는 _EntryPoint@16으로, C++로 쓰여진 경우는 함수명을 장식한다. 그러므로 장식돤 이름을 사용하지 않으려면, .DEF 파일을 사용하고, 이름으로 엔트리 포인트 함수를 익스포트해야 한다.
    Rundll 엔트리 포인트의 매개변수는 다음과 같다:
    hwnd - DLL에서 사용할 오너 윈도우의 윈도우 핸들
    hinst - DLL의 인스턴스 핸들
    lpszCmdLine - DLL이 분석해야할 ASCIIZ 커맨드 라인
    nCmdShow - DLL의 윈도우를 디스플레이할 방법

    다음은 예이다:
    RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF
    Rundll은 Setupx.dll 내의 InstallHinfSection() 엔트리 포인트 함수를 다음의 매개 변수로 콜한다:
    hwnd = (모 윈도우 핸들)
    hinst = SETUPX.DLL의 HINSTANCE 
    lpszCmdLine = "132 C:\WINDOWS\INF\SHELL.INF"
    nCmdShow = (CreateProcess에 전달되는 nCmdShow)
    주 : 엔트리 포인트 함수(예제에서는 InstallHinfSection())는 커맨드 라인 (여기에서는 lpszCmdLine)을 분석한다. Rundll.exe는 커맨드 라인에 패스되는 아규먼트중 옵션 아규먼트까지 분석하고 나머지 분석은 엔트리 포인트 함수에 의존한다. 

    * 윈도우 95와 윈도우 NT간의 차이점

    윈도우 NT에서의 Rundll32.exe동작은 유니코드 커맨드 라인에 적합하도록 되어있다. 윈도우 NT는 먼저 <엔트리 포인트 함수명>W의 GetProcAddress를 얻어내어 엔트리 포인트가 있는 경우 함수 원형을 다음으로 간주한다:
    void CALLBACK
    EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow);
    이것은 lpszCmdLine이 유니코드 문자열인 점만이 ANSI 엔트리포인트 함수와 다른 점이다. 

    만약 <엔트리 포인트 함수명>W이 없으면, 윈도우 NT는 <엔트리 포인트 함수명>을 위하여 <엔트리 포인트 함수명>A의 GetProcAddress를 실행하고 이를 ANSI 엔트리 포인트로 여겨 윈도우 95와 동일하게 처리한다. 그러므로, 만약 작성한 DLL이 윈도우 95에서는 ANSI 지원, 윈도우 NT에서는 UNICODE지원하게 한다면 반드시 두개의 함수: EntryPointW 와 EntryPoint를 익스포트한다. 윈도우 NT에서 EntryPointW 함수는 유니코드 커맨드 라인을 사용하고, 윈도우95에서는 EntryPoint 함수는 ANSI 커맨드 라인을 콜하게 될 것이다.


    728x90

    'Program > DLL' 카테고리의 다른 글

    dll 멀웨어 파일 실행 방법  (0) 2016.11.30
    INFO: Windows Rundll 및 Rundll32 인터페이스  (0) 2016.11.30
    728x90
    요약
    Microsoft Windows 95, Windows 98 및 Windows Millennium Edition(Me)에는 16비트나 32비트 DLL에서 내보낸 함수를 호출하는 데 사용되는 Rundll.exe와 Rundll32.exe라는 두 가지 명령줄 유틸리티 프로그램이 포함되어 있습니다. 그러나 Rundll과 Rundll32 프로그램을 통해 임의의 DLL에서 내보낸 함수 모두를 호출할 수 있는 것은 아닙니다. 예를 들어, 이러한 유틸리티 프로그램을 사용하여 시스템 DLL에서 내보낸 Win32 API(응용 프로그래밍 인터페이스) 호출을 수행할 수는 없으며, 이들 프로그램이 호출하도록 명시적으로 작성된 함수만 DLL에서 호출할 수 있습니다. 이 문서에서는 위에서 언급한 Windows 운영 체제에서 Rundll 및 Rundll32 프로그램을 사용하는 방법에 대해 자세히 설명합니다. 

    MIcrosoft Windows NT 4.0, Windows 2000 및 Windows XP에는 Rundll32만 제공됩니다. 이러한 플랫폼에서는 Rundll(Win16 유틸리티)을 지원하지 않습니다. 

    Rundll 및 Rundll32 유틸리티 프로그램은 원래 Microsoft 내부에서만 사용하도록 설계되었습니다. 그러나 이들 프로그램에서 제공하는 기능이 상당히 일반적이기 때문에 지금은 일반적인 용도로 사용할 수 있습니다. Windows NT 4.0에는 Rundll32 유틸리티 프로그램만 제공되므로 Windows NT 4.0은 Rundll32만 지원합니다.
    추가 정보

    Rundll과 Rundll32 비교

    Rundll은 16비트 DLL을 로드하고 실행하는 반면 Rundll32는 32비트 DLL을 로드하고 실행합니다. 잘못된 유형의 DLL을 Rundll이나 Rundll32로 전달하면 오류 메시지가 표시되지 않고 실행되지 않을 수 있습니다.

    Rundll 명령줄

    Rundll의 명령줄은 다음과 같습니다.
    
       RUNDLL.EXE <dllname>,<entrypoint> <optional arguments>
    				
    예를 들면, 다음과 같습니다.
    
       RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF
    				
    위의 명령줄에서 신중하게 고려할 세 가지 사항이 있습니다.
    1. Rundll이나 Rundll32는 표준 위치에서 주어진 DLL 파일 이름을 검색합니다(자세한 내용은 LoadLibrary() 함수에 대한 문서 참조). DLL을 제대로 검색하기 위해 DLL의 전체 경로를 제공하는 것이 좋습니다. 최상의 결과를 얻으려면 잘못된 문자가 나타나지 않도록 긴 파일 이름 대신 짧은 파일 이름을 사용합니다. 특히 "C:\Program Files" 폴더의 DLL이 짧은 이름으로 변환되어야 합니다.
    2. <dllname>에는 공백, 쉼표 또는 따옴표가 포함되지 않을 수 있습니다. 이것은 Rundll 명령줄 파서의 제한 사항입니다.
    3. 위의 명령줄에서 <dllname>과 <entrypont> 함수 이름 사이의 쉼표(,)는 매우 중요합니다. 쉼표 구분 기호가 없으면 Rundll이나 Rundll32는 오류를 표시하지 않고 실패합니다. 또한, <dllname>, 쉼표 및 <entrypoint> 함수 사이에는 공백이 있어서는 안 됩니다.

    Rundll의 작동 방식

    Rundll은 다음 단계를 수행합니다.
    1. 명령줄 구문을 분석합니다.
    2. LoadLibrary()를 통해 지정된 DLL을 로드합니다.
    3. GetProcAddress()를 통해 <entrypoint> 함수의 주소를 얻습니다.
    4. <entrypoint> 함수를 호출하고 명령줄 끝 정보인 <optional arguments>를 전달합니다.
    5. <entrypoint> 함수가 결과를 반환하면 Rundll.exe는 DLL을 언로드하고 종료됩니다.

    DLL을 작성하는 방법

    DLL에서 다음 프로토타입을 사용하여 <entrypoint> 함수를 작성합니다. 

    16비트 DLL: 

    
      void FAR PASCAL __loadds
      EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
    				
    32비트 DLL:
    
      void CALLBACK
      EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
    				
    EntryPoint 함수에서 고려할 세 가지 사항이 있습니다.
    1. "EntryPoint"라는 이름을 작성한 진입점 함수의 실제 이름으로 바꿔야 합니다. Rundll32의 진입점은 프로세스와 스레드 연결/분리 알림을 처리하는 32비트 DLL의 DllEntryPoint 함수와는 전혀 관계가 없습니다.
    2. Rundll32의 진입점 함수는 _stdcall 호출 규칙을 사용하여 정의되어야 합니다(콜백은 _stdcall 특성을 사용하도록 기본적으로 설정됨). _stdcall 특성이 없으면 함수는 _cdecl 호출 규칙을 기본적으로 사용하고 Rundll32는 함수를 호출한 후 비정상적으로 종료됩니다.
    3. 위에서 설명한 대로 _stdcall 호출 규칙을 사용하여 함수를 선언해야 하므로 Visual C++ 컴파일러는 DLL이 C로 작성된 경우 이것을 _EntryPoint@16으로 내보내고 DLL이 C++로 작성된 경우 이름 장식을 더 사용합니다. 따라서 명령줄에서 Rundll이나 Rundll32에 대해 제대로 내보낸 이름을 사용하도록 해야 합니다. 장식된 이름을 사용하지 않으려면 .def 파일을 사용하고 이름에 따라 진입점 함수를 내보냅니다. Visual C++ 컴파일러를 사용하는 경우의 이름 장식에 대한 자세한 내용은 제품 설명서와 다음 문서를 참조하십시오.
      140485 INFO: 32비트 DLL에서 PASCAL 형식의 기호 내보내기
    Rundll 진입점에 대한 매개 변수는 다음과 같습니다.
       hwnd - DLL이 만든 모든 창에 대해 소유자 창으로 사용되는
              창 핸들
       hinst - DLL의 인스턴스 핸들
       lpszCmdLine - DLL이 구문 분석하는 ASCIIZ 명령줄
       nCmdShow - DLL의 창이 표시되는 방법 설명
    				
    다음 예제에서
    
         RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF
    				
    Rundll은 Setupx.dll에서 InstallHinfSection() Entrypoint 함수를 호출하고 다음 매개 변수를 전달합니다.
       hwnd = (부모 창 핸들)
       hinst = SETUPX.DLL의 HINSTANCE
       lpszCmdLine = "132 C:\WINDOWS\INF\SHELL.INF"
       nCmdShow = (CreateProcess로 전달된 모든 nCmdShow)
    				
    이것은 자체 명령줄(위의 lpszCmdLine 매개 변수)의 구문을 분석하고 필요에 따라 개별 매개 변수를 사용해야 하는 <entrypoint> 함수(위의 예제에서는 InstallHinfSection())입니다. Rundll.exe는 명령줄로 전달된 선택적 인수의 구문까지만 분석합니다. 나머지 구문 분석은 <entrypoint> 함수가 담당합니다.

    Windows 95와 Windows NT의 차이점

    Windows NT, Windows 2000 및 Windows XP에서는 유니코드 명령줄을 수용하기 위해 Rundll32.exe의 동작이 약간 다릅니다. 

    Windows NT는 먼저 <EntryPoint>W에 대한 GetProcAddress를 실행합니다. 이 진입점을 찾은 경우 프로토타입은 다음과 같습니다.
    
       void CALLBACK
       EntryPointW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine,
                   int nCmdShow);
    				
    이것은 lpszCmdLine 매개 변수가 유니코드 문자열이라는 점을 제외하고는 ANSI EntryPoint와 동일합니다. 

    <EntryPoint>W 진입점을 찾지 못하면 Windows NT는 <entrypoint>A 및 <entrypoint>에 대한 GetProcAddress를 실행합니다. 둘 중 하나가 발견되면 ANSI 진입점으로 간주되고 Windows 95/98/Me와 같은 방식으로 처리됩니다. 따라서 ANSI가 지원되는 Windows 95와 유니코드가 지원되는 Windows NT/2000/XP에서 DLL을 실행하려고 하면 두 함수 EntryPointW와 EntryPoint를 내보내야 합니다. Windows NT/2000/Me에서 EntryPointW 함수는 유니코드 명령줄에서 호출되고 Windows 95/98/Me에서 EntryPoint 함수는 ANSI 명령줄에서 호출됩니다.


    728x90

    'Program > DLL' 카테고리의 다른 글

    dll 멀웨어 파일 실행 방법  (0) 2016.11.30
    [INF] 윈도우 95의 Rundll과 Rundll32의 사용법  (0) 2016.11.30
    728x90


    연산자

    연산자의 의미

    결합성

    =

    오른쪽에 있는 값을 왼쪽에 대입한다.

    Ex) a = 20

    +

    왼쪽과 오른쪽에 있는 값을 더한다.

    Ex) a = 4 + 3

    -

    왼쪽에 있는 값에서 오른쪽에 있는 값을 뺀다.

    Ex) a = 4 – 3

    *

    왼쪽과 오른쪽에 있는 값을 곱한다.

    Ex) a = 4 * 3

    /

    왼쪽에 있는 값을 오른쪽에 있는 값으로 나눈다.

    Ex) 4 / 3

    %

    왼쪽에 있는 값을 오른쪽에 있는 값으로 나눠서 나머지를 반환한다.

    Ex) a = 4 % 3

    ++a

    값을 1 증가 후 연산을 진행(선 증가, 후 연산)

    Ex) printf(“%d”, ++a)

    a++

    연산을 진행한 후 값을 1 증가(선 연산, 후 증가)

    Ex) printf(“%d”, a++)

    --b

    값을 1 감소 후 연산을 진행(선 감소, 후 연산)
    ex) printf(“%d”, --b)

    b--

    연산을 진행한 후 값을 1 감소(선 연산, 후 감소)

    Ex) printf(“%d”, b--)

    <

    Ex) a < b

    a가 b보다 작은가?

    >

    Ex) a > b

    a가 b보다 큰가?

    ==

    Ex) a == b

    a와 b가 같은가?

    !=

    Ex) a != b

    a와 b가 같지 않은가?

    <=

    Ex) a <= b

    a가 b보다 작거나 같은가?

    >=

    Ex) a >= b

    a가 b보다 크거나 같은가?

    &&

    피연산자가 모두 참이면 true를 반환(and의 의미)

    Ex) a && b

    ||

    피연산자 중 하나라도 참이면 true를 반환(or의 의미)

    Ex) a || b

    !

    피연산자가 true면 false를, false면 true를 반환(not의 의미)

    Ex) !a

    &

    비트 단위 AND

    Ex) a & b

    |

    비트 단위 OR

    Ex) a | b

    ^

    비트 단위 XOR

    Ex) a ^ b

    ~

    비트 단위 NOT

    Ex) ~a

    <<

    왼쪽으로 이동

    Ex) a << 2

    >>

    오른쪽으로 이동

    Ex) a >> 2

     

    자료형(data type)

    할당되는 메모리 크기

    표현 가능한 데이터의 범위

    char

      1 바이트

      -128 ~ +127

     short

      2 바이트

      -32768 ~ +32767

     int

      4 바이트

      -2147483648 ~ +2147483647

     long

      4 바이트

    -2147483648 ~ +2147483647

     float

      4 바이트

      3.4X  ~ 3.4X 

     double

      8 바이트

      1.7X  ~ 1.7X 

     long double

      8 바이트 혹은 그 이상

      차이를 많이 보임

     

    특수 문자

    의     미

    \a(\a)

    경고음 소리 발생

    \b

    백스페이스(backspace)

    \f

    폼 피드(form feed)

    \n

    개행

    \r

    캐리지 리턴(carriage return)

    \t

    수평 탭

    \v

    수직 탭

    \\

    백슬래시(\)

    \’

    작은 따옴표

    \”

    큰 따옴표

     

    서식 문자

    출력 형태

    %c

    단일 문자

    %d

    부호 있는 10진 정수

    %i

    부호 있는 10진 정수, %d와 같음

    %f

    부호 있는 10진 실수

    %s

    문자열

    %o

    부호 없는 8진 정수

    %u

    부호 없는 10진 정수

    %x

    부호 없는 16진 정수, 소문자 사용

    %X

    부호 없는 16진 정수, 대문자 사용

    %e

    표기법에 의한 실수(부동소수점 표현 방식)

    %E

    표기법에 의한 실수(부동소수점 표현 방식)

    %g

    값에 따라서 %f, %e 둘 중 하나를 선택

    %G

    값에 따라서 %f, %E 둘 중 하나를 선택

    %%

    기호 출력

    %αd

    필드 폭을 α칸 확보하고 오른쪽 정렬해서 출력하라.

    %-αd

    필드 폭을 α칸 확보하고 왼쪽 정렬해서 출력하라.

    %+αd

    필드 폭을 α칸 확보하고 오른쪽 정렬한 상태에서 양수는 +, 음수는 –를 붙여서 출력하라.



    728x90

    + Recent posts