https://www.codeproject.com/Articles/522094/Outlook-add-in-using-VCplusplus-ATL-COM

' > URL' 카테고리의 다른 글

펌] 각 언어별 딥러닝~ 라이브러리.  (0) 2017.01.17
CUDA  (0) 2016.12.12
GIT 튜토리얼.  (0) 2016.12.08
NVIDIA, CUDA  (0) 2016.11.23

MFC로 프로그래밍을 하다 보면, 각 클래스에 어떻게 접근해서 포인터를 얻어와야 하는지 매우 어려울 때가 많다...

특히 초중급자 시절엔 말이다.. 사용한 지 오래 되어도 여전히 헷갈리기는 매 한가지다.

자 그럼.. 하나씩.. 이해해 보자.


우선 MFC로 프로그램을 만들면, 다음과 같이 클래스가 생성된다. 프로젝트 명을 Test라고 가정해 보자.


CTestApp - CWinApp 클래스를 상속, 프로그램 초기화 클래스 (InitInstance)

CMainFrame - CFrameWnd 클래스를 상속, 전체 윈도우 관련 클래스(툴바, 메뉴, 상태바 등등)

CTestDoc - CDocument 클래스를 상속, 문서 관련 클래스(Open, Save, Serialize)

CTestView - CView 클래스를 상속, 사용자 화면 클래스(OnPaint, OnDraw)

CAboutDlg - CDialog 클래스를 상속, 도움말 대화 상자 클래스(DoModal)


-------------------------------------------------*^^*--------------------------------------------------


우선 가장 쉬운 것부터 설명하자면,

어느 곳에서나 CTestApp의 포인터를 얻고자 한다면, 다음과 같이 코딩한다.

AfxGetApp()는 전역 함수이므로 어느 곳에서나 호출할 수 있다.


CTestApp* pApp = AfxGetApp();


하지만 위와 같이 사용하면, 다음과 같은 에러가 발생한다.


error C2440: 'initializing' : cannot convert from 'class CWinApp *' to 'class CTestApp *'

에러를 보면, CWinApp*를 CTestApp*로 변환할 수 없다는 것인데, AfxGetApp()의 함수 원형이


CWinApp* AfxGetApp();


이기 때문이다. 그래서 이 문제를 해결하기 위해서는 아래와 같이 형변환(casting)을 해 주어야 한다.


CTestApp* pApp = (CTestApp*)AfxGetApp();


이제는 컴파일 에러 없이 잘 될 것이다. 그리고 다음과 같은 에러가 발생될 수도 있느데,


error C2065: 'CTestApp' : undeclared identifier


이는 CTestApp 클래스의 선언 부분이 포함(include)되지 않았기 때문이다. 이럴 때는

CTestApp 클래스의 선언을 다음처럼 포함시켜야 한다.


#include "Test.h"


pApp는 이미 생성되어 있는 CTestApp의 객체 포인터이기 때문에,

이젠 pApp 포인터를 통해 CTestApp 객체에 쉽게 접근할 수 있다. 만약에 CTestApp에


int i;


라는 멤버 변수가 있었다면,


pApp->i = 5;


와 같이 사용할 수 있다. 또한 멤버 함수 func()가 있다면,


pApp->func();


처럼 접근할 수 있다. 주의해야 할 것은 객체 접근이기 때문에 public 속성의 멤버들만 접근할 수 있고,

private와 protected는 접근할 수 없음에 유의해야 한다.


-------------------------------------------------*^^*--------------------------------------------------


두 번째는 CMainFrame의 포인터을 얻어 오는 방법이다. 다음과 같이 사용하려 할 때,


CMainFrame* pFrame = AfxGetMainWnd();


두 가지 에러와 만나게 된다.

첫 번째, CMainFrame에 대해서 컴파일러가 모르겠다는 에러이다.


error C2065: 'CMainFrame' : undeclared identifier

이 에러를 수정하기 위해서는 CMainFrame 클래스가 선언되어 있는 헤더 파일을

다음처럼 포함시키면 된다. 그리고 포함시키는 위치도 Test.h와 TestDoc.h 사이가 좋다.

그것은 클래스들간에 서로 관계가 있기 때문에 포함 순서는 매우 중요하다.


#include "stdafx.h"
#include "Test.h"


#include "MainFrm.h"


#include "TestDoc.h"
#include "TestView.h"

이 에러를 해결하고 나면, 다음과 같이 CTestApp에서 발생했던 에러가 발생한다.


error C2440: 'initializing' : cannot convert from 'class CWnd *' to 'class CMainFrame *'

에러를 보면, CWnd*를 CMainFrame*로 변환할 수 없다는 것인데, AfxGetMainWnd()의 함수 원형이


CWnd* AfxGetMainWnd();


이기 때문이다. 그래서 이 문제를 해결하기 위해서는 아래와 같이 형변환(casting)을 해 주어야 한다.


CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();


이제는 컴파일 에러 없이 잘 될 것이다. CMainFrame은 CFrameWnd를 상속 받고, CFrameWnd는

CWnd를 상속 받기 때문에, pFrame 포인터를 통해서 CFrameWnd와 CWnd가 갖고 있는 모든 함수를

호출하여 사용할 수 있다. 만약 윈도우의 타이틀에 나오는 제목을 바꾸고 싶다면,


pFrame->SetWindowText( "야.. 바뀌어라" );


처럼 사용하면 된다.


-------------------------------------------------*^^*--------------------------------------------------


CMainFrame*는 또 다른 이유로 자주 사용하게 되는데, 그 이유는 도큐먼트(CTestDoc)와

뷰(CTestView) 클래스에 접근하기 위해서이다. CMainFrame 클래스는 뷰에 접근하는 GetActiveView(); 함수와

문서에 접근하는 GetActiveDocument() 함수를 제공한다.


우리가 어느 특정 클래스를 만들어서 사용하고, 이 클래스가 뷰에 접근해야 한다면 다음과 같은 문장을 사용해야 한다.


CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

CTestView* pView = (CTestView*)pFrame->GetActiveView();


만약 도큐먼트 클래스에 접근해야 한다면,


CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

CTestDoc* pDoc = (CTestDoc*)pFrame->GetActiveDocument();

 

물론 이 때는 각각의 클래스에 대한 헤더를 반드시 포함시켜야 함을 잊지 말아야 된다.

가끔 아래와 같은 순서로 헤더를 포함시키지 않는 경우가 있는데, 반드시 아래와 같이 포함해야 한다.


#include "MainFrm.h"

#include "TestDoc.h"

#include "TestView.h"


만약 대화 상자에서 도큐먼트 클래스에 접근하려면 어떻게 할 것인가? 방법은 위와 동일하다.


-------------------------------------------------*^^*--------------------------------------------------

 

다음은 뷰에서 도큐먼트에 접근하는 것과 도큐먼트에서 뷰에 접근하는 것에 대해 알아보자.

뷰와 도큐먼트는 서로를 직접 접근할 수 있는 함수가 제공된다. 뷰에서 도큐먼트를 직접 접근하려면,

 

CTestDoc* pDocument = (CTestDoc*)GetDocument();

 

를 호출하면 된다. 물론 View 클래스에는 GetDocument() 함수가 존재해야 한다. 일반적으로 이 함수는

MFC로 프로젝트 생성 시 기본적으로 있다. 하지만 만약 직접 만든 새로운 클래스라면 GetDocument() 함수를

직접 만들어줘야 한다. 직접 만들기가 귀찮다면, 다음과 같이 사용해도 된다.

 

CTestDoc* pDocument = (CTestDoc*)m_pDocument;

 

m_pDocument는 CTestView 클래스의 멤버이며, 다음과 같이 선언되어 있다.

 

CDocument* m_pDocument;


그리고, 도큐먼트에 뷰 클래스를 참조하려면 아래와 같이 해야 한다.


POSITION pos = GetFirstViewPosition();
CTestView* pView = (CTestView*)GetNextView( pos );

도큐먼트는 뷰 클래스를 내부적으로 링크드리스트를 사용해서 관리하고 있다. 그러므로 GetFirstViewPosition()

함수를 통해 POSITION을 얻어 온 다음, GetNextView() 함수를 통해 뷰의 포인터를 얻어오면 된다.

만약 창 분할에 의해 뷰가 여러 개 존재한다면, 다음과 같이 얻어 올 수 있다. 만약 컴파일 에러가 발생하면,

#include "TestView.h" 처럼 해서 헤더 파일을 포함하는 것도 잊지 말자.


POSITION pos = GetFirstViewPosition();
CTestView1* pView1 = (CTestView1*)GetNextView( pos );

CTestView2* pView2 = (CTestView2*)GetNextView( pos );
CTestView3* pView3 = (CTestView3*)GetNextView( pos );
CTestView4* pView4 = (CTestView4*)GetNextView( pos );
...


-------------------------------------------------*^^*--------------------------------------------------

 

그렇다면,,, CTestApp 클래스에서 뷰(CTestView) 클래스는 어떻게 얻어 올 수 있을까? 쉽게 응용할 수 있지만

머리가 꽉 막힐 수도 있다. 이 곳에서도 혹시 에러가 나면 헤더 파일을 자~알 추가해야 할 것이다.

 

CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CTestView* pView = (CTestView*)pFrame->GetActiveView();


 

-------------------------------------------------*^^*--------------------------------------------------

 

마지막으로, 뷰(CTestView) 클래스에서 CMainFrame에 접근할 수 있는데 AfxGetMainWnd() 함수외에도

 

CMainFrame* pFrame = (CMainFrame*)GetParentFrame();

 

-------------------------------------------------*^^*--------------------------------------------------

 

MDI 환경에서 포인터를 가져와 보자.

 

CTestApp* pApp = (CTestApp*)AfxGetApp();

POSITION pos = pApp->GetFirstDocTemplatePosition();
    
CDocTemplate* pDocTemplate;
pDocTemplate = pApp->GetNextDocTemplate( pos );
  // 첫 번째 등록한 템플릿
pDocTemplate->OpenDocumentFile( NULL );               // 첫 번째 문서 생성

 

POSITION posDoc = pDocTemplate->GetFirstDocPosition();
CTestDoc* pDoc = (CTestDoc*)pDocTemplate->GetNextDoc( posDoc );
  // 첫 번째 문서 포인터
ASSERT( pDoc->IsKindof( RUNTIME_CLASS(CMongDoc) ) );                   // 포인터 유효성 검사
//CXXXDoc* pDoc2 = (CXXXDoc*)pDocTemplate->GetNextDoc( posDoc );             // 두 번째 문서 포인터

POSITION posView = pDoc->GetFirstViewPosition();
CTestView* pView = (CTestView*)pDoc->GetNextView( posView );
       // 첫 번째 뷰 포인터
ASSERT( pView->IsKindof( RUNTIME_CLASS(CTestView) ) );                // 포인터 유효성 검사

//CXXXView* pView2 = (CXXXView*)pDoc->GetNextView( posView );                 // 두 번째 뷰 포인터
//ASSERT( pView2->IsKindof( RUNTIME_CLASS(CXXXView) ) );                         // 포인터 유효성 검사

// 다음 템플릿이 존재할 경우만 가능합니다.

pDocTemplate = pApp->GetNextDocTemplate( pos );  // 두 번째 등록한 템플릿
if( pDocTemplate )                                                         
// 두 번째 템플릿이 존재하는지 검사

{

    pDocTemplate->OpenDocumentFile( NULL );          // 두 번째 문서 생성

}

 

-------------------------------------------------*^^*--------------------------------------------------

 

분할 뷰에서는 위의 방법과 같이 포인터를 얻어 올 수 있다. 또는 다음과 같은 방법으로 얻어 올 수 있다.

만약 창이 두 개로 분할되어 있다면,

 

CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

CTestView* pView1 = (CTestView*)pFrame->m_wndSplitter.GetPane(0,0);   // 첫 번째 뷰 포인터 얻기

CXXXView* pView2 = (CTestView*)pFrame->m_wndSplitter.GetPane(0,1);   // 두 번째 뷰 포인터 얻기


뷰 포인터는 다음과 같이 좌표를 사용하여 구할 수 있다.


---------------------------------------------

|                                |                               |

|      GetPane( 0, 0 )       |     GetPane( 0, 1 )       |

|                                |                               |

---------------------------------------------

|                                |                               |

|      GetPane( 1, 0 )    |     GetPane( 1, 1 )     |

|                                |                               |

--------------------------------------------------------------------

|                                |                               |                                 |

|      GetPane( 2, 0 )    |     GetPane( 2, 1 )     |     GetPane( 2, 2 )             |

|                                |                               |                                 |

--------------------------------------------------------------------


펌:http://egloos.zum.com/indra207/v/5175542


' > WIN32 MFC' 카테고리의 다른 글

파일 관련 API 정리.  (0) 2016.11.22

DirectX SDK (June 2010) 을 Windows 7 에 설치하던 중에 Error Code S1023 이 뜹니다.

원인은 최신 버전의 Visual C++ 2010 X86/X64 Redistributable Package 가 설치되어서 발생되는 것입니다.


일단 이것들을 제어판에서 삭제합니다.

DOS 명령어에서 다음과 같이 입력해도 삭제됩니다.

MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}
MsiExec.exe /passive /X{1D8E6291-B0D5-35EC-8441-6616F567A0F7}


그 다음에 DirectX SDK 를 설치합니다.

http://www.microsoft.com/en-us/download/details.aspx?id=6812


그 다음에 최신 버전의 Visual C++ 2010 X86/X64 Redistributable Package 를 설치합니다.

http://www.microsoft.com/ko-kr/download/details.aspx?id=26999


참고



출처: http://appmaid.tistory.com/11 [App Maid]

프로그래밍 언어별 딥러닝 라이브러리 정리

AI Korea Open 그룹에서도 라이브러리에 관한 투표가 있었고, 많은 분들이 관심있어할 만한 부분이라 생각해서 한 번 정리해 봤습니다!

dl_library_vote (AI Korea Open 그룹의 투표 결과)

Python

요즘 뜨는 언어답게, 대부분의 라이브러리들이 빠른 속도로 업데이트되며 새로운 기능이 계속 추가되고 있다.

  1. Theano - 수식 및 행렬 연산을 쉽게 만들어주는 파이썬 라이브러리. 딥러닝 알고리즘을 파이썬으로 쉽게 구현할 수 있도록 해주는데, Theano 기반 위에 얹어서 더 사용하기 쉽게 구현된 여러 라이브러리가 있다.
    • Keras - Theano 기반이지만 Torch처럼 모듈화가 잘 되어 있어서 사용하기 쉽고 최근에도 계속 업데이트되며 빠른 속도로 발전하고 있는 라이브러리.
    • Pylearn2 - Theano를 유지, 보수하고 있는 Montreal 대학의 Yoshua Bengio 그룹에서 개발한 Machine Learning 연구용 라이브러리
    • Lasagne - 가볍고 모듈화가 잘 되어 있어서 사용하기 편리함
    • Blocks - 위 라이브러리와 비슷하게 역시 Theano 기반으로 손쉽게 신경망 구조를 구현할 수 있도록 해주는 라이브러리
  2. Chainer - 거의 모든 딥러닝 알고리즘을 직관적인 Python 코드로 구현할 수 있고, 자유도가 매우 높음. 대다수의 다른 라이브러리들과는 다르게 "Define-by-Run" 형태로 구현되어 있어서, forward 함수만 정의해주면 네트워크 구조가 자동으로 정해진다는 점이 특이하다.
  3. nolearn - scikit-learn과 연동되며 기계학습에 유용한 여러 함수를 담고 있음.
  4. Gensim - 큰 스케일의 텍스트 데이터를 효율적으로 다루는 것을 목표로 한 Python 기반 딥러닝 툴킷
  5. deepnet - cudamat과 cuda-convnet 기반의 딥러닝 라이브러리
  6. CXXNET - MShadow 라이브러리 기반으로 멀티 GPU까지 지원하며, Python 및 Matlab 인터페이스 제공
  7. DeepPy - NumPy 기반의 라이브러리
  8. Neon - Nervana에서 사용하는 딥러닝 프레임워크

Matlab

  1. MatConvNet - 컴퓨터비젼 분야에서 유명한 매트랩 라이브러리인 vlfeat 개발자인 Oxford의 코딩왕 Andrea Vedaldi 교수와 학생들이 관리하는 라이브러리.
  2. ConvNet - CNN 라이브러리
  3. DeepLearnToolbox - DBN, Stacked Autoencoder, CNN 등의 딥러닝을 위한 matlab/octave 툴박스

C++

  1. Caffe - Berkeley 대학에서 관리하고 있고, 현재 가장 많은 사람들이(추정) 사용하고 있는 라이브러리. C++로 직접 사용할 수도 있지만 Python과 Matlab 인터페이스도 잘 구현되어 있다.
  2. DIGITS - NVIDIA에서 브라우저 기반 인터페이스로 쉽게 신경망 구조를 구현, 학습, 시각화할 수 있도록 개발한 시스템.
  3. cuda-convnet - 딥러닝 슈퍼스타인 Alex Krizhevsky와 Geoff Hinton이 ImageNet 2012 챌린지를 우승할 때 사용한 라이브러리
  4. eblearn - 딥러닝 계의 또하나의 큰 축인 NYU의 Yann LeCun 그룹에서 ImageNet 2013 챌린지를 우승할 때 사용한 라이브러리
  5. SINGA - 기존의 시스템에서 동작하는 분산처리 학습 알고리즘을 일반적으로 구현하기 위해 만들어진 플랫폼으로 Apache Software Foundation의 후원을 받고 있다.

Java

  1. ND4J - N-Dimensional Arrays for Java. JVM을 위한 과학 연산 라이브러리로 상용 제품에 사용될 수 있게 연산들이 최소한의 메모리 사용으로 빠르게 작동하게 끔 만들어졌다.
  2. Deeplearning4j - Java와 Scala로 작성된 첫 상용 수준의 오픈소스 분산처리 딥러닝 라이브러리. 개발툴보다는 business 환경에 적합하도록 작성되었다.
  3. Encog -머신러닝 프레임워크로 SVM, ANN, Genetic Programming, Genetic Algorithm, Bayesian Network, Hidden Markov Model 등을 지원한다.

JavaScript

자바스크립트로의 딥러닝 구현은 Stanford의 Andrej Karpathy가 혼자서 개발했음에도 불구하고 높은 완성도를 보이며 널리 사용되고 있는 아래 두 라이브러리가 가장 유명하다.

  1. ConvnetJS - 딥러닝 모델의 학습을 완전히 브라우저에서 할 수 있게 하는 자바스크립트 라이브러리. 별도의 소프트웨어, 컴파일러, 설치, GPU 없이 쉽게 사용할 수 있다.
  2. RecurrentJS - RNN/LSTM을 구현한 Javascript 라이브러리

Lua

  1. Torch - 페이스북과 구글 딥마인드에서 사용하는 라이브러리. 양대 대기업에서 사용하고 있는 만큼 필요한 거의 모든 기능이 잘 구현되어 있고, 스크립트 언어인 Lua를 사용하기 때문에 쉽게 사용 가능하다.

Julia

MIT에서 새로 개발한 언어로, 최근에 주목받기 시작하여 효율적인 딥 러닝 라이브러리도 여러 가지 구현되었다.

  1. Mocha.jl - C++ 프레임워크인 Caffe에 영감을 받아 만들어진 Julia 기반의 딥러닝 프레임워크. Mocha의 General stochastic solver와 공통 레이어를 사용해 deep / shallow(convolutional) neural network를 학습하고 (stacked) auto-encoder를 통해 unsupervised pre-training을 할 수 있다. 모듈화된 구조, 하이 레벨 인터페이스, 이식성, 빠른 속도, 호환성등을 특징으로 한다.
  2. Strada.jl - Caffe 프레임워크를 기반으로 해 만들어진 오픈소스 딥러닝 라이브러리. CNN과 RNN을 CPU/GPU로 학습할 수 있다.
  3. KUnet.jl - 최대한 적은 양의 코드로 작성하고자 하는 시도에서 만들어진 딥러닝 패키지. 현재 1000 라인 미만의 코드로 여러 네트워크, activation, optimization을 구현하고 있고, CPU/GPU를 사용해 Caffe와 비슷한 성능으로 학습할 수 있다고 한다.

Lisp

  1. Lush - Lisp Universal Shell. 대규모 수치, 그래픽 어플리케이션을 위한 객체 지향 프로그래밍 언어. 딥러닝 라이브러리가 머신러닝 라이브러리에 포함되어 제공된다.

Haskell

  1. DNNGraph - Haskell로 작성된 deep neural network 모델 생성 DSL(domain-specific language)

.NET

  1. Accord.NET - C#으로만 작성된 .NET 머신러닝 프레임워크로 음성, 이미지 처리 라이브러리가 포함되어 있다. 상용 수준의 컴퓨터 비전, 컴퓨터 음성인식, 신호처리, 통계 어플리케이션을 만들 수 있다.

R

  1. darch - 레이어가 많은 neural network(deep architecture)를 만들 수 있다. contrastive divergence로 pre-training 하거나 backpropagation, conjugate gradient와 같은 알고리즘을 사용한 fine tuning으로 학습할 수 있다.
  2. deepnet - BP, RBM, DBN, Deep autoencoder 등의 딥러닝 아키텍쳐, neural network 알고리즘을 구현한 패키지.

출처: http://www.teglor.com/b/deep-learning-libraries-language-cm569/ 블로그 포스트 자료에서 약간의 수정을 거쳤습니다.

작성자: 최명섭, 김주용

Written on September 10, 2015


' > URL' 카테고리의 다른 글

OUTLOOK PLUG IN  (0) 2018.04.04
CUDA  (0) 2016.12.12
GIT 튜토리얼.  (0) 2016.12.08
NVIDIA, CUDA  (0) 2016.11.23

커널함수는 비동기 함수이기 때문에, 동기화 처리시, cudaDeviceSynchronie() 함수를 호출하면 된다.

' > CUDA' 카테고리의 다른 글

스트림.  (0) 2017.01.04
고정 메모리와 제로 메모리 그리고 포터블 메모리.  (0) 2017.01.03
메모리 타입.  (0) 2017.01.03
CUDA 컴파일 옵션.  (0) 2017.01.03
쓰레드 ID 구하기.  (0) 2016.12.29

 - 소개.

   쿠다는 아래와 같이 처리를 하는데, 데이터를 복사하는 과정과 GPU 처리 과정이 순차적으로 처리가 되기 때문에, 1번 과정에서 GPU는 대기하게 되어, 동시성이 떨어진다.

   이와 같이  대기 시간을 줄이기 위해, 데이터를 작은 단위로 나뉘고 데이터 전송이 완료된 것 부터 GPU에서 계산하는 동시에 계속해서 데이터를 전송하도록 개선 했는데,  이를 스트림이라고 한다.


   1. 호스트에서 디바이스로 입력 데이터 복사.

   2. 커널함수 데이터 처리.

   3. 처리결과를 디바이스->호스트로 복사.


 -특징

    -  순차적으로 처리를 해야 하는 의존적인 데이터에 대해서도 스트림은 순차적으로 처리를 한다.

    -  cudaMallocHost() 를 이용해서 고정된 메모리[pinned Memory] 사용해야 한다.

    -  커널함수<<<1,2,3,stream>>>() - 4번재 항목에 적용된다. 명시하지 않으면 기본값 stream 0 이 할당된다.



- 관련 API

   1. cudaStreamCreate()   

   2. cudaMemcpyAsync();

   3. cudaStreamDestroy()



- 샘플코드



__global__ void kernel( int*In, int*Out)
{
    int tid = blockIdx.x * blockDim.x+ threadIdx.x;

    for(int i=0;i<5;i++)
        Out[tid] += In[tid];
}

int main()
{
    const int nStreams = 15;        //스트림 분할 개수
    const int nBlocks = 65535;      //블록의 개수
    const int nThreads = 512;       //스레드의 개수
    const int N = 512*65535;        //데이터의 개수
    const int Size = N*sizeof(int); //버퍼의 사이즈

    int* host_In;
    int* host_Out;

    //호스트 메모리 할당
    cudaMallocHost((void**)&host_In,Size);
    cudaMallocHost((void**)&host_Out,Size);

    //데이터 입력
    for( int i = 0; i < N; i++)
    {
        host_In[i] = i;
        host_Out[i] = 0;
    }

    int* dev_In;
    int* dev_Out;

    //디바이스 메모리 할당
    cudaMalloc((void**)&dev_In, Size);
    cudaMalloc((void**)&dev_Out, Size);

    cudaMemset(dev_In, 0, Size);
    cudaMemset(dev_Out, 0, Size);
       
    
    //스트림 객체 생성
    cudaStream_t *streams = (cudaStream_t*) malloc(nStreams * sizeof(cudaStream_t));

    for(int i = 0; i < nStreams; i++)
        cutilSafeCall( cudaStreamCreate(&(streams[i])) );

    
    //병행 실행 시간 측정
    cudaEvent_t StreamStart, StreamStop;
    float StreamTime;

    cudaEventCreate(&StreamStart);
    cudaEventCreate(&StreamStop);

    int offset = 0;

    cudaEventRecord(StreamStart, 0);

    //호스트 디바이스 입력 데이터 전송
    for(int i = 0; i < nStreams; i++)
    {
        offset= i*N/nStreams;
        cudaMemcpyAsync(dev_In + offset, host_In + offset, Size, cudaMemcpyHostToDevice, streams[i]);
    }

    //덧셈 계산
    for(int i = 0; i < nStreams; i++)
    {
        offset= i*N/nStreams;
        kernel<<<nBlocks/nStreams,nThreads, 0, streams[i]>>>(dev_In+offset, dev_Out+offset);
    }

    //디바이스 호스트 출력 데이터 전송
    for(int i = 0; i < nStreams; i++)
    {
        offset= i*N/nStreams;
        cudaMemcpyAsync(host_Out + offset, dev_Out + offset, Size, cudaMemcpyDeviceToHost, streams[i]);
    }

    cudaEventRecord(StreamStop, 0);
    cudaEventSynchronize(StreamStop);

    cudaEventElapsedTime(&StreamTime, StreamStart, StreamStop);


    printf("스트림 실행시간: %f msec\n",StreamTime);
    

    cudaEventDestroy(StreamStart);
    cudaEventDestroy(StreamStop);

    for(int i = 0; i < nStreams; i++)
        cudaStreamDestroy(streams[i]);

    cudaFree(dev_In);
    cudaFree(dev_Out);

    cudaFreeHost(host_In);
    cudaFreeHost(host_Out);

    return 0;
}

 

' > CUDA' 카테고리의 다른 글

커널함수  (0) 2017.01.16
고정 메모리와 제로 메모리 그리고 포터블 메모리.  (0) 2017.01.03
메모리 타입.  (0) 2017.01.03
CUDA 컴파일 옵션.  (0) 2017.01.03
쓰레드 ID 구하기.  (0) 2016.12.29

1. 고정메모리.

    - 가상메모리를 사용하지 않고, 메모리에 직접 접근하여 처리하는 접근 방식.

    - 가상 메모리와 물리적 메모리간의 치환 제거.

    - CUDA 스트림을 사용하기 위해서는 고정 메모리는 필수다.

    

   - 관련 함수 

     1. cudaMallocHost

     2. cudaFreeHost 


2. 제로 메모리.

   - 호스트와 디바이스간에 메모리 복사를 하지 않고, 고정된 메모리[Pinned Memory]영역에 바로 엑세스하여 데이터를 읽고 쓸수 있는 메모리.

   - PCI를 사용해서 전송 속다가 빨라 지는 것은 아니지만.

   - 데이터를 계산하고, 결과값을 메모리에 쓰면 비동기 양방향 PCI 전송이 진행되기 때문에, 그 만큼 성능향상을 볼 수 있다.


   - 전제조건

      - 맵드 메모리를 사용할 때, 글로벌 메모리의 결합 전송과 동일한 조건을 커널에서 충족시켜야 한다. 


       글로벌 메모리 결합 전송조건.

        - 글로벌 메모리를 읽어 올 때 최대 밴드 폭을 사용할 수 있는 조건  - 사실 최신 사양에서는 무시해도 되지 않나 싶다.[개인생각]




    - 주의-

      - 커널에서 작은 크기의 데이터를 많은 횟수로 맵드 메모리를 엑세스 하게 되면, 통상적인 데이터 전송보다 떨어지는 효과를 얻을 수 있다.


   - 관련 함수

      1  cudaHostAlloc

      2  cudaHostGetDevicePointer 

      3 예제: 


3.포터블 고정 메모리.

- 제로 메모리는 하나의 디바이스에서만 유효하기 때문에, 두개의 디바이스상에서 문제가 된다.  즉 두개의 호스트 스레드를 생성하여 처리하게 되는데, 이 때 하나의 스레드에서 생성한 고정된 메모리는 다른 쓰레드에서는 사용할 수 없게 되어, 자원 낭비를 하게 된다.


이런 자원 낭비를 피하고자 사용하는 것이 포터블 고정 메모리라고 한다.  


- 적용.

   cudaHostAlloc() 세번째 파라미터: cudaHostAllocMapped | cudaHostAllocPortable 옵션 지정.




 


' > CUDA' 카테고리의 다른 글

커널함수  (0) 2017.01.16
스트림.  (0) 2017.01.04
메모리 타입.  (0) 2017.01.03
CUDA 컴파일 옵션.  (0) 2017.01.03
쓰레드 ID 구하기.  (0) 2016.12.29






- 메모리 타이별 특성.

  1. 레지스터 

     - 쓰래드 내부에서 몇 개를 사용하는지는 알 수 없다. 다만 툴을 이용해서 확인은 가능.

     - 단항연산을 할수록, 사용하는 레지스터 갯수는 줄어든다.

     

              

  2. 로컬메모리

    - 쓰레드 로컬에서 사용
    -  제한된 레지스터 개수를 초과하면 로컬 메모리에 할당된다.
    - 레지스터냐, 로컬이냐 할당 기준은 명확하지 않다.

  3. 공유메모리 Shared Memory

       



      - 소개 : 블록내 할당된 쓰레드 간에 공유되는 메모리.
      - 특성 :
           - SM과 인접하기 때문에, 메모리양이 적고, 속도가 빠르다.
           - 워프에 의해 영향을 받는다.
           - 같은 크기의 메모리를 32개 가진다.  뱅크 갯수는 Compute ability 테이블을 참조한다.  = 32개. 보통 warp 갯수와 동일하다고 한다.
           - 병행성을 위해, 메모리 뱅크 개념을 알아야 함.
           - 뱅크 내 메모리 단위는 4byte/8byte 로 구성할 수 있고. API로 설정 가능하다.

           - 동기화. 필요.
               __synchthread();

      - 선언.
         1. __shared__ float tile[size_y][size_x]; 
         2. extern __shared__ int tile[];  
             - 사이즈가 결정되지 않았을 때 사용한다.
             - 커널 함수를 호출할 때 명시하면 된다.  kernel<<<grid, block, shared_memory_size>>>(....);                            

         3. 커널내부, 외부에서 선언할 수 있다. 

    
      - 메모리 뱅크 
        - 메모리 밴드를 최대한 활용 목적으로  병행성을 극대화 하기 위해, 같은 크기의 메모리 블록을[64K/ 32[뱅크갯수] ] 32개 가진 메모리 모듈를 뱅크라고 한다.       
        - 계산식 : 뱅크 수 32개. 
                 1 열은 32 * 4 바이트 = 128 BYTE
                 2. 한 열의 뱅크 크기[4바이트 / 1블록  크기] =  1024 * 64  / 128  = 512개.     

                   0번 스레드 -->뱅크 0   [ 0 BYTE] [128BYTE]  ~~~~
                   1번 쓰레드 --> 뱅크 1  [4 BYTE][132BYTE ]
                     ~~
                  31번 쓰레드 --> 뱅크 31 [ 124 BYTE][252BYTE]


         - 관련 이슈: 뱅크 충돌.
             - 2개 이상의 쓰레드가 동시에 하나의 뱅크에 접근하려고 했을 때 뱅크 충돌이라고 한다.
             - 뱅크 충돌시, 처리는 순차적으로 이루어지기 때문에,   1/ 충돌횟수 만큼 성능이 떨어지게 된다.


      - 동기화.
          1. 공유메모리는 비동기적으로 처리가 되기 때문에, 동기화 작업이 필요하다.
          2. __synchthreads() 를 통해 동기화가 이루어진다.                     
              

  4. 글로벌 메모리.

     -  디바이스의 DRAM을 말한다.
     -  cudaMalloc() 호출시 할당되는 메모리.


  5. 상수 메모리.

     -읽기 전용. / 캐쉬 지원 
     - 호스트영역: 쓰기전용
     - 디바이스영역: 읽기 전용.

     쓰기 예)
       __constant__ int cData[6];
       
       int aData[6] = {1, 2, 3, 4, 5, 6};
      cudaMemcpyToSymbol ("cData",&aData,sizeof(aData));

       

  6. 텍스트 메모리.

    2.2 이후로 지원안함.


   


' > CUDA' 카테고리의 다른 글

스트림.  (0) 2017.01.04
고정 메모리와 제로 메모리 그리고 포터블 메모리.  (0) 2017.01.03
CUDA 컴파일 옵션.  (0) 2017.01.03
쓰레드 ID 구하기.  (0) 2016.12.29
Nsight - Performance Analysis  (0) 2016.12.29

-maxrregcount  : 쓰레드당 사용할 수 있는 레지스터 개수를 지정할 수 있다.

                       초과 되었을 경우, 로컬 메모리[DRAM] 를 사용하게 된다. 

 

 


' > CUDA' 카테고리의 다른 글

고정 메모리와 제로 메모리 그리고 포터블 메모리.  (0) 2017.01.03
메모리 타입.  (0) 2017.01.03
쓰레드 ID 구하기.  (0) 2016.12.29
Nsight - Performance Analysis  (0) 2016.12.29
CUDA Debugging - Nsight  (0) 2016.12.29

1D grid of 1D blocks

__device__ int getGlobalIdx_1D_1D()

{

return blockIdx.x *blockDim.x + threadIdx.x;

}


1D grid of 2D blocks

__device__ int getGlobalIdx_1D_2D()

{

return blockIdx.x * blockDim.x * blockDim.y + threadIdx.y * blockDim.x + threadIdx.x;

}


1D grid of 3D blocks

__device__ int getGlobalIdx_1D_3D()

{

return blockIdx.x * blockDim.x * blockDim.y * blockDim.z + threadIdx.z * blockDim.y * blockDim.x + threadIdx.y * blockDim.x + threadIdx.x;


2D grid of 1D blocks 

__device__ int getGlobalIdx_2D_1D()

{

int blockId   = blockIdx.y * gridDim.x + blockIdx.x;

int threadId = blockId * blockDim.x + threadIdx.x; 

return threadId;

}


2D grid of 2D blocks  

 __device__ int getGlobalIdx_2D_2D()

{

int blockId = blockIdx.x + blockIdx.y * gridDim.x; 

int threadId = blockId * (blockDim.x * blockDim.y) + (threadIdx.y * blockDim.x) + threadIdx.x;

return threadId;

}


2D grid of 3D blocks

__device__ int getGlobalIdx_2D_3D()

{

int blockId = blockIdx.x 

+ blockIdx.y * gridDim.x; 

int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)

  + (threadIdx.z * (blockDim.x * blockDim.y))

  + (threadIdx.y * blockDim.x)

  + threadIdx.x;

return threadId;


3D grid of 1D blocks

__device__ int getGlobalIdx_3D_1D()

{

int blockId = blockIdx.x 

+ blockIdx.y * gridDim.x 

+ gridDim.x * gridDim.y * blockIdx.z; 

int threadId = blockId * blockDim.x + threadIdx.x;

return threadId;


3D grid of 2D blocks

__device__ int getGlobalIdx_3D_2D()

{

int blockId = blockIdx.x 

        + blockIdx.y * gridDim.x 

+ gridDim.x * gridDim.y * blockIdx.z; 

int threadId = blockId * (blockDim.x * blockDim.y)

 + (threadIdx.y * blockDim.x)

 + threadIdx.x;

return threadId;

}


3D grid of 3D blocks

__device__ int getGlobalIdx_3D_3D()

{

int blockId = blockIdx.x 

+ blockIdx.y * gridDim.x 

+ gridDim.x * gridDim.y * blockIdx.z; 

int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)

 + (threadIdx.z * (blockDim.x * blockDim.y))

 + (threadIdx.y * blockDim.x)

 + threadIdx.x;

return threadId;

}



' > CUDA' 카테고리의 다른 글

메모리 타입.  (0) 2017.01.03
CUDA 컴파일 옵션.  (0) 2017.01.03
Nsight - Performance Analysis  (0) 2016.12.29
CUDA Debugging - Nsight  (0) 2016.12.29
CUDA Visual Profiler  (0) 2016.12.28

+ Recent posts