영상이 보이지 않으면 이곳을 클릭해서 실버라이트를 설치하세요

Visual Studio 2010 출시 몇 시간 만에 Visual Studio 2010 e-book 이 나왔습니다.

 

내용 전체가 포함된 것이 아니라, PREVIEW CONTENT 만 포함되어 있습니다. 하지만 내용상으로 기초적인 내용에서 약간의 중급적인 내용이 포함이 되어있어 한번씩 보시면 도움이 될 것 같습니다.

아직 책이 완성본은 아닙니다. 아마도 예정대로라면 2010년 여름쯤이면 책의 모든 콘텐트가 업데이트 될 것 같습니다.

Moving to Visual Studio 2010 e-book 
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=560a5365-5c62-488a-91ed-a779e0e33ac4 

Visual Studio 2010 공식 팀 블로그의 트위터

안녕하세요. Visual Studio 2010 공식 팀 블로그에서는 트위터를 통해 여러분들과 소통을 하고 있습니다.

   

Visual Studio 2010 Launch Live 를 트위터로 생중계

VS2010 팀의 트위터를 통해 라스베가스의 Bellagio Hotel 에서 생방송으로 진행된 Visual Studio 2010 Launch Live 를 생중계 하였습니다. Visual Studio 2010 Launch Live 는 아래의 링크에서 다시 볼 수 있습니다.

http://www.microsoft.com/presspass/presskits/developer/videogallery.aspx?contentID=devlaunch10_d1keynote

   

트위터의 #vs2010korea 해시태그 커뮤니케이션 오픈

한국에서 Visual Studio 2010 을 사용하는 사람들을 위한 태그입니다. 여러분이 어디에 있든, 무엇을 하든, #vs2010korea 는 여러분들의 이야기에 듣고 있습니다. ^^

Visual Studio 2010 의 질문/답변/팁/노하우/잡담/구매/이슈 등 여러분들의 이야기를 #vs2010korea 라는 하나의 태그로 묶고 싶습니다.

   

   

많은 참여 바랍니다.

드디어 Visual Studio 2010 이 출시가 되었습니다. Subscribe to MSDN 을 통해 다운로드 할 수 있습니다.

다운로드
https://msdn.microsoft.com/ko-kr/subscriptions/securedownloads/default.aspx

   

 

초기 Visual Studio CTP 와 Beta 버전에서 많은 논란이 있었습니다. 하지만 Visual Studio 개발팀의 많은 노력과 결실이 Visual Studio RC 에서 상당수가 개선이 되었습니다.    

  

이번 메이저 업그레이드 버전에서 많은 사용자의 피드백을 통해 많은 버그 들이 수정이 되었답니다. 얼마나 많은 사용자가 참여를 했고, Fixed 버전이 나왔는지 아래의 Microsoft Connect 사이트를 통해 확인할 수 있습니다.

https://connect.microsoft.com/VisualStudio

   

또한, 저희 Visual Studio 2010 에서 팀원을 추가로 모집하고 있습니다. 관심있는 분들은 아래의 링크를 참고하세요.

http://vsts2010.net/248

   

저희 팀 블로그는 트위터를 운영하고 있습니다. 빠른 소식을 전달해 드리고, 커뮤니케이션의 장을 열어드릴 것입니다.

자 그럼 Visual Studio 2010 의 세계로 떠나봅시다. 아직 잘 모르시겠다고요?? 그럼 아래의 저희 Visual Studio 2010 의 블로그 포스트를 차근 차근 살펴보시기 바랍니다.

 

Visual Studio 2010
Visual Studio 2010
Visual Studio 2010! 나랑 놀아보자 – 기본편 (4회) - Call Hierarchy
Visual Studio 2010! 나랑 놀아보자 – 기본편 (3회) - Box Selection
Visual Studio 2010! 나랑 놀아보자 – 기본편 (2회) - VS IDE
윈도우폰 7 개발환경 공개
실버라이트4 RC와 블렌드 4 베타 공개
똑똑한 검색을 지원하는 VSTS 2010의 "Navigate To" 검색
C#에서 IntelliSense가 동작하지 않을 때 문제 해결 방법
Visual Studio 2010 RC 공개
Visual Studio 2010 RC 공개 임박!
VS 2010 기능소개 05 - Visual C#&VB 개발자 IDE Tips & Tricks 두번째
VS 2010 기능소개 04 - Visual C#&VB 개발자 IDE Tips & Tricks 첫번째
VS 2010 기능 소개 03 - IDE의 변화
VS 2010 기능 소개 02 - IDE의 기능 추가
Visual Studio 2010 출시 일정
VS 2010 기능 소개 01 인텔리 센스 기능의 변화
Visual Studio 2010과 Blend Preview for .NET 4 통합 문제
VS2010 베타2의 WPF & Silverlight 디자이너 성능 향상 팁
VS 2010 Beta 2 설치 과정에서 Silverlight SDK 문제
Visual Studio 2010 Beta 2 설치 미리 보기
Visual Studio 2010 Beta 2 출시
멀티 모니터 사용
Visual Studio 2010 Beta 1 설치부터 살펴보기
Visual Studio 2010 & .NET 4.0 참고 자료들
Visual Studio 2010 내부 빌드 최신 동영상: C# 4.0 Language + IDE + WPF Shell + Editor
Visual Studio 2010 의 특징

Visual Studio Extensibility
Visual Studio 2010 확장 모델인 VSIX 버그
[VSX] 1. Visual Studio Extensibility,, 그 시작
MousePresentationTracker - MEF 세미나 예제
[VSIX] 2-2. How to start VSIX programming
[VSIX] 2-1. How to start VSIX programming
[VSIX] 1. What is different from before version?
Visual Studio 2010 Extension Manager
Visual Studio 2010 SDK 와 Readme
[Blueprints] S+S Blueprints

 

Language
C#
[C# 4.0] Generic Covariance And Contra Variance
[C# 4.0] New Extension Method "Zip"
[C# 4.0] Duck Typing
[C# 4.0] Named and Optional Parameters
Welcome to Dynamic C#(14) - 철지난 만우절에 낚여서 파닥파닥.
Welcome to Dynamic C#(13) - 아직도 가야할 길.
Welcome to Dynamic C#(12) - dynamic은 외로운 아이.
Welcome to Dynamic C#(11) - The Phantom of The Dynamic
Welcome to Dynamic C#(10) - Dynamic Returns Again.(2)
Welcome to Dynamic C#(9) - Dynamic Returns Again.
Welcome to Dynamic C#(8) - DLR이 나무를 사랑하는 이유
Welcome to Dynamic C#(7) - 아낌없이 표현해 주는 나무
Welcome to Dynamic C#(6) - Return to Dynamic (2)
Welcome to Dynamic C#(5) - Return to Dynamic.
Welcome to Dynamic C#(4) - 극과극 비교체험.
Welcome to Dynamic C#(3) - 마음이 넒어진 C#
Welcome to Dynamic C#(2) - Wanna be a polyglot.
Welcome to Dynamic C#(1) - 첫만남.
Welcome to dynamic C# 외전(3) - 감시하는 자와 감시당하는 자.
Welcome to dynamic C# 외전(2) - Generic Method.
Welcome to dynamic C# 외전(1) - Generate From Usage.

CLR (Common Language Runtime)
8. System.Object (2)
7. System.Object
6. Assembly - GAC(Global Assembly Cache)
5. Assembly - Strongly named assemblies
4. Assembly
3. MSCorLib & Metadata
2. CLR! CLR! CLR!
1. Hello 世界

F#
Welcome to F#(12) - 공동작업 좋치아니항가
Welcome to F#(11) - 차별을 권장하는 언어인거임?!?!
Welcome to F#(10) - 인도음식 카레.....?
Welcome to F#(9) - 메이져 데뷰.
Welcome to F#(8) - 은총알과 엄친아.
Welcome to F#(7) - 클리프 행어.
Welcome to F#(6) - 비교본능.
Welcome to F#(5) - 아주 조금씩 심화되는 탐색전.
Welcome to F#(4) - 과거와 배경을 좀 더 알고싶어.
Welcome to F#(3) - 사소한 탐색전.
Welcome to F#(2) - 두번째 만남.
Welcome to F#(1) - 첫만남.    

C++0x
[VC++] 14. decltype
[VC++] 13. Lambda - 네 번째
[VC++] 12. Lambda - 세 번째
[VC++] 11. Lambda - 두 번째
[VC++] 9. Lambda ( 람다 ) - 첫 번째
[VC++] 8. 우측 값 참조( RValue Reference ) – 다섯 번째
[VC++] 7. 우측 값 참조( RValue Reference ) - 네 번째
[VC++] 6. 우측 값 참조( RValue Reference ) - 세 번째
[VC++] 5. 우측 값 참조( RValue Reference ) – 두 번째
[VC++] 4. 우측 값 참조( RValue Reference ) - 첫 번째
[VC++] 3. static_assert
[VC++] 2. C++0x의 auto
[VC++] 1. 큰 변화가 기대되는 Visual C++( VC++ )
VC++ 10에 구현된 C++0x의 코어 언어 기능들
nullptr
대용량 파일 조작을 위한 C++0x의 변화

C++0x Parallel Programming
C++ 개발자를 위한 병렬 프로그래밍 동영상 [6/7] 완결!
C++ 개발자를 위한 병렬 프로그래밍 동영상 [5]
C++ 개발자를 위한 병렬 프로그래밍 동영상 [4]
C++ 개발자를 위한 병렬 프로그래밍 동영상 [3]
C++ 개발자를 위한 병렬 프로그래밍 동영상 [2]
C++ 개발자를 위한 병렬 프로그래밍 동영상 [1]
C++ 개발자를 위한 병렬 프로그래밍 동영상 [0]
양보할 줄 아는 Concurrency Runtime의 event
Parallel Patterns Library (PPL)
Concurrency Runtime
인사 및 Multi Core, Multi Thread...그리고 VC++ 10
PPL task를 이용한 피보나치 수 계산
Parallel Patterns Library(PPL) - concurrent_queue - 2
Parallel Patterns Library(PPL) - concurrent_queue - 1
Parallel Patterns Library(PPL) - concurrent_vector - 2
Parallel Patterns Library(PPL) - concurrent_vector - 1
Parallel Patterns Library(PPL) - parallel_for_each 알고리즘
Parallel Patterns Library(PPL) - parallel_for 알고리즘
Parallel Patterns Library(PPL) - 병렬 알고리즘
Parallel Patterns Library(PPL) - Task
Parallel Patterns Library(PPL) - combinable
Parallel Patterns Library(PPL) - parallel_invoke
Parallel Patterns Library(PPL) - task group에서의 병렬 작업 취소 - 2
Parallel Patterns Library(PPL) - task group에서의 병렬 작업 취소 - 1
Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 마지막회
Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 2
Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 1 

Visual C++ 10
2010/02/04 디버깅 모드에서 역어셈블리 코드 보기
2009/10/15 About Visual C++ 10    

MFC
[MFC] 태스크 대화상자(Task Dialog) - 예제 코드 올립니다.
[MFC] 태스크 대화상자(Task Dialog) - (3/3) : 활용하기
[MFC] 태스크 대화상자(Task Dialog) - (2/3) : 사용하기
[MFC] 태스크 대화상자(Task Dialog) - (1/3) : 기능 소개
[MFC] 리스타트 매니저(Restart Manager) - (3/3) : 활용하기
[MFC] 리스타트 매니저(Restart Manager) - (2/3) : 사용하기
[MFC] 리스타트 매니저(Restart Manager) - (1/3) : 기능 소개

   

.NET Framework
Parallel Programming
Welcome to Parellel world(1) - Here comes a new challenger!
[C# 4.0] Parallel Extension - [3] TPL(Task Parallel Library)
[C# 4.0] Parallel Extension - [2] 병렬 처리 아키텍처
[C# 4.0] Parallel Extension - [1] 병렬 처리

Managed Extensibility Framework
MEFGeneric 코드 플랙스에 공개합니다.
MEF 에 Generic Type 을 지원하기 위해서..?
MEF 는 Generic Type 을 지원하지 않는다!
MEF Preview 6 공개
[MEF] 10. Querying the CompositionContainer
[MEF] 9. Recomposition
[MEF] 8. Strongly Typed Metadata
[MEF] 7. Exports and Metadata
[MEF] 6. Lazy Exports
[MEF] 5. Catalog 사용
[MEF] 4. Import 선언
[MEF] 3. Export 선언
[MEF] 2. Parts 와 Contracts 선언
[MEF] 1. Managed Extensibility Framework 이란?

WCF
WCF 서비스의 동시성(Concurrency) - 2
WCF 서비스의 동시성(Concurrency) - 1
WCF의 기본 <Contract> - Data Contract
WCF의 기본 <Contract> - Service Contract
기본 WCF 프로그래밍 - 첫 WCF 서비스 만들기 2
기본 WCF 프로그래밍 - 첫 WCF 서비스 만들기
WCF란 무엇인가?

 

Web Development
ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(1)
ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - New Features in the Microsoft Ajax Library
ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Core Services
ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Designer & Deployment
ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Dynamic Data(2)

ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Dynamic Data(1)
[ASP.NET 4.0] 2. AJAX - Declarative Client Template Rendering
[ASP.NET 4.0] 1. Core Service - Extensible Output Caching    

M, V 그리고 C의 각방생활(3) - 초간단 사이트 만들기(1)
M, V 그리고 C의 각방생활(2) - ASP.NET MVC와 인사나누기
M, V 그리고 C의 각방생활(1) - ASP.NET MVC vs ASP.NET WEB FORM    

   

Cloud Development
[MS@클라우드컨퍼런스] MS 클라우드 기술과 플랫폼
SQL Azure 알아보기 (5)- SQL Azure 이점과 T-SQL 지원
SQL Azure 알아보기(4) – SQL Azure Cloud App
SQL Azure 알아보기(3) –SQL Server 2008 R2 Nov CTP
SQL Azure 사용 시 주의점(1) - 방화벽 설정
구름 속의 미래 : Windows® Azure™ Platform [2]
SQL Azure 알아보기(2) – 데이터베이스 스키마 마이그레이션, 데이터 전송
SQL Azure 알아보기 (1) - 데이터베이스 개체 생성
SQL Azure - CTP1
구름 속의 미래 : Windows® Azure™ Platform [1]

   

Windows 7 Development
[멀티터치]멀티터치 프로그래밍 환경 구축하기
사람이 기계와 만나는 진정한 방법 - 멀티터치
[Windows7] Win32를 이용해 윈도우7 멀티터치 프로그래밍하기
Windows 7을 위한 Windows XP 모드
Windows SDK 설치 후 XAML 인텔리센스 문제

 

Sharepoint 2010
SharePoint 2010 Server Object Model
SharePoint 2010 데이터 기술
SharePoint 2010 Event Receiver
SharePoint 2010 Feature
SharePoint 2010 Visual Web Part
SharePoint 2010 Web Part 생성
SharePoint 2010 개발 환경- Hello World 웹 파트 생성 및 배포하기
SharePoint 2010 개발 환경 구성
SharePoint 2010 Overview

   

Architecture Development
Windows Server AppFabric - Velocity 란?
몽당연필과 함께 하는 VSTS 2010 모델링 1/4
몽당연필과 함께하는 VSTS 2010 모델링 0/4
Architect Development ?

   

Agile Development
애자일에 대한 고찰
[Better Code]Visual Studio Code Analysis Enhancements - 3. Data Flow Rules and Phoenix Engine
[Testing] Moq.NET (T/B Driven Development)

[Testing] BDD (Behavior-Driven Development–행위 주도 개발)
[Testing] TDD (Test-Driven Development-테스트 주도 개발)
[Better Code]Visualize Code Relationships
[Better Code]PEX, Automated Whitebox Testing for .NET - 1. 개요
[Better Code]Visual Studio 2010 Code Analysis Enhancements - 2. Rule Sets Feature
[Better Code]Visual Studio 2010 Code Analysis Enhancements - 1.개요
[Better Code]TDD의 개념이 완벽히 녹아 들어간 VSTS 2010

   

Team Foundation Server
Team Foundation 트러블 슈팅 가이드
Visual Studio 2010을 활용한 ALM (1-5) - ALM 이란 무엇인가
TFS 2010 설치 과정 중에 TF255040 문제
TFS 2010 Build Service 설치
TFS 2010 설치 하기

[JumpToDX11-11] DirectCompute 를 위한 한걸음!

DirectX 11 2010. 2. 11. 09:00 Posted by 알 수 없는 사용자


앞선 시간을 통해서 GPGPU 를 위해서 마이크로소프트가 제공하는 플랫폼이
DirectCompute 라는 것이라고 말씀드렸습니다.
앞으로 DirectX11 을 지원하는 모든 그래픽카드들은 이 DirectCompute 를 지원할 것입니다.
그 이외에도 일부 DirectX10 을 지원하는 그래픽카드들도 지원을 하고 있습니다.


GPGPU 를 위해서 가장 기본적이고 핵심이 되는 기능은 무엇일까요?
저는 GPU 에서 처리된 메모리를 CPU 쪽의 메모리로 보내는 것이라고 생각합니다.
( 이는 개인 의견입니다.^^ )
즉, 그래픽카드에 있는 메모리를 메인메모리로 보내는 작업입니다.
DirectX9 세대까지는 이 작업이 불가능 했습니다.
예를 들면, 그래픽스 파이프라인 중간에 처리된 결과를 다시 가공할 수 있는 방법은
VertexShader 나 PixelShader 같은 쉐이더 스테이지 정도 뿐이였습니다.

하지만 DirectX10 부터는 이들에 대한 중간 결과를 메인메모리로 보내는 기능이 추가되어지면서,
GPGPU 의 시작을 알렸다고 생각합니다.
이 단순한 Copy 작업이 앞으로도 얼마나 유용하게 사용될 수 있을지는 기대가 상당합니다.



< DirectCompute 를 위한 ComputeShader >

DirectCompute 를 위해서 개발자가 할 일은 ComputeShader 를 작성하는 일입니다.
ComputeShader 는 HLSL 이라는 기존 DirectX 의 쉐이더 문법 구조로 작성을 합니다.




HLSL 코드는 DirectX 쉐이더 컴파일러인 FXC 나 API 를 통해서 컴파일 됩니다.
HLSL 은 결국 최적화된 IL 코드를 생성하게 되고,
이 IL 코드를 기반으로 런타임에 각각의 하드웨어에 최적화된 명령어들로 변환
되어져서 실행됩니다.


< GPGPU 에게 실행이란? >

GPGPU 를 활용해서 실행한다는 것은 하드웨어 내부적으로 어떻게 동작하도록 할까요?
앞선 시간에 GPU 는 병렬 처리에 최적화된 많은 SIMD 형태로 구성되어져 있다고 언급했었습니다.
결국 이들은 스레드들의 그룹으로써 실행합니다.
스레드들을 얼마나 많이 생성할 것인지를 개발자가 정해주면, 그에 맞게 연산을 수행합니다.

API 에서는 이들을 큰 그룹으로 나누어 줍니다.
큰 그룹으로 나누어 주는 API 는 ID3D11DeviceContext::Dispatch() 입니다.

ipImmediateContextPtr->Dispatch( 3, 2, 1 );

이렇게 큰 블럭 단위로 나누고 난 후에
ComputeShader HLSL 에서는 이들을 세부적인 스레들로 분할하는 문법을 지정합니다.

[numthreads(4, 4, 1)]
void MainCS( ... )
{
        ....
}




결과적으로 위의 그림처럼 스레드들이 생성되어서 병렬적으로 실행이 됩니다.
위에 나열된 숫자들은 스레드 ID 로써의 역활을 합니다.
즉, 어떤 스레드의 ID 가 MainCS 함수에 파라메터로 넘오오면,
그 ID 를 통해서 해당 버퍼에 값을 작성하게 됩니다.

아래에 간단한 예가 있습니다. 

[numthreads( 256,1,1) ]

void VectorAdd( uint3 id: SV_DispatchThreadID )
{

  gBufOut[id] = gBuf1[id] + gBuf2[id];

}


아무리 스레드들이 복잡하게 동작하더라도, 위와 같이 ID 를 통해서 제어한다면
그 어떤 작업도 문제없이 할 수 있습니다.

일단 먼저 어떻게 DirectCompute 가 실행되어지는지에 대해서 살펴보았습니다.
실행까지 가기 위해서는 일련의 절차를 거쳐야 합니다.
이들에 대해서는 앞으로 차근차근 살펴보겠습니다.



참고 자료
http://microsoftpdc.com/Sessions/P09-16
본 내용은 위의 PDC 를 참고해서 만들었습니다.

[JumpToDX11-9] Multi-threaded Rendering 을 위한 API.

DirectX 11 2010. 1. 11. 09:00 Posted by 알 수 없는 사용자



이번 시간에는 Multi-threaded Rendering 을 위한 API 들에 대해서 살펴보겠습니다.
기능 위주의 설명을 위해서 인자들에 대한 명시는 생략했습니다.
이점 주의해주시기 바랍니다.

ID3D11Device::CreateDeferredContext()

가장 먼저 살펴볼 것은 DeferredContext 의 생성입니다.
DeferredContext 는 스레드당 하나씩 생성되어질 수 있음을 앞선 시간을 통해서 언급했습니다.
또한 이 DeferredContext 는 Command List 들을 생성해서 가지고 있습니다.
즉, 렌더링이 가능한 상태라는 것입니다.
그런 기능을 우리는 Device 인터페이스를 통해서 생성합니다.
이것은 역시 Free thread 한 작업이기 때문에 Device 인터페이스를 이용합니다.

하나의 DeferredContext 는 thread-safe 합니다.
즉, 스레드 상에서 DeferredContext 가 관련 Command 들을 기록하는 것은 안전한 작업입니다.

간단한 사용 방법은 아래와 같습니다.
ID3D11DeviceContext* pDeferredContext = NULL;
hr = g_pd3dDevice->CreateDeferredContext(0, &pDeferredContext);


ID3D11DeviceContext::FinishCommandList()

신기하게도 우리는 이 API 호출 한번으로 CommandList 들을 기록하고 생성할 수 있습니다.
API 이름이 Finish 여서 Start나 Begin 계열의 API 를 검색해 보았지만, 없었습니다.^^
각각의 DeferredContext 별로 호출되기 때문에 DeviceContext 의 멤버함수로 되어 있습니다.
앞선 시간을 통해서 DeviceContext 는 ImmeidateContext 와 DeferredContext 로
분리될 수 있다고 언급했었습니다.
두 Context 모두 ID3D11DeviceContext 인터페이스를 사용하기 때문에 오해의 소지가 약간 있습니다.
FinishCommandList 는 DeferredContext 를 위한 API 임을 유념하시기 바랍니다.

간단한 사용 방법은 다음과 같습니다.
ID3D11CommandList* pd3dCommandList = NULL;
hr = pDeferredContext->FinishCommandList( FALSE, &pd3dCommandList );


ID3D11DeviceContext::ExecuteCommandList()

이 API는 DeferredContext 에 의해서 생성된 CommandList 들을 실행합니다.
역시나 ID3D11DeviceContext 의 멤버함수이기 때문에 혼란스러울 수 있습니다.
과연 ImmediateContext 가 이 함수를 호출할까요? 아니면, DeferredContext 일까요?

지난 시간들을 통해서 우리는 실제로 Multi-threaded Rendering 이라는 것은
CommandList 생성을 Multi-thread 기반으로 하는 것이라고 언급했었습니다.
그 이후에 실제 그래픽 카드로의 전송은 하나의 스레드만 할 수 있다고 했었습니다.
바로 그 사실입니다.
이 함수는 ImmediateContext 에 의해서 호출됩니다.
즉, 이 API 는 그래픽 카드로 해당 CommandList 들을 전송하는 것입니다.

간단한 사용 방법은 아래와 같습니다.
g_pImmediateContext->ExecuteCommandList( g_pd3dCommandList, TRUE );


이상 3가지 API 에 대해서 살펴보았습니다.
믿기지 않으시겠지만(?)
Multi-threaded Rendering 작업은 이 세가지 API로 할 수 있습니다.
나머지는 스레드 생성과 제어를 위한 작업이 결합되어야 할 것입니다.
일반적인 스레드 프로그래밍과 관련된 내용이라 이곳에서는 배제를 했습니다.
현재 DirectX SDK Sample 에는 'MultithreadedRendering11' 라는 것이 있습니다.( 2009 August 버전 기준 )
이것과 관련된 소스가 있으니 참고해서 보시면 좋을 것 같습니다.

이상으로 Multi-threaded Rendering 의 기본 개념 설명을 마치고자 합니다.
이 부분과 관련된 내용은 앞으로 정리가 되는대로 추가하거나 수정이 되어질 수 있을 것입니다.
다음 시간부터는 DirectX11 의 다른 주제를 가지고 돌아오겠습니다.^^
 

[JumpToDX11-8] Deferred Contexts

DirectX 11 2009. 12. 2. 09:00 Posted by 알 수 없는 사용자

멀티스레드 기반의 렌더링을 위해서 DirectX11 에서는 세가지를 중점에 두었습니다.

- 비동기적으로 자유스러운 리소스 로딩과 관리.
  ( 이들은 렌더링과 동시에 수행될 수 있어야 한다. )

- 멀티스레드 형식으로 렌더링 커맨드의 생성.
  ( 여러 스레드로 나누어서 렌더링 작업을 할 수 있어야 한다. )

- 디스플레이 리스트( Display lists )의 지원.


첫번째 리소스와 관련한 것을 지난 시간에 알아보았습니다.
이제는 실제 렌더링 작업에 대해 알아보아야 합니다.
그 실제 렌더링 작업을 위해서 우리는 새롭게 등장한 Deferred Context 라는 것을 살펴볼 것입니다.
Deferred Context 가 멀티스레드 기반의 렌더링에서 가장 중요한 키워드입니다.

< Device 의 분리 >
지난 세대의 DirectX는 모든 GPU 관련 내용의 처리는 Device 인터페이스를 통해서 수행했습니다.
즉 지난 회들에서 꾸준히 언급했던 것처럼,
Device 인터페이스를 통해서만 커맨드( Command ) 를 생성할 수 있었습니다.



오직 싱글코어 기반으로 설계된 지난 세대의 DirectX 였기 때문에,
위의 그림과 같은 상황이 연출되었습니다.
이들에 대한 내용은 지난 시간을 통해서 꾸준히 언급되었기 때문에, 더 자세한 언급은 하지 않겠습니다.

Device 인터페이스에 모든 작업이 집중되어 있었기 때문에,
이를 분리할 방법이 필요했습니다.
그 기준은 앞서 언급했듯이, 
그래픽카드에 보내는 작업이 Free threaded 한지였습니다.
결론적으로 얘기 드리면 DirectX11 에서는 기존의 Device 가 분리에 분리를 거듭했습니다.
그래서 아래와 같은 구조로 되었습니다.





DirectX11 에서 이제 개발자가 다루어야하는 커맨드 생성 인터페이스는 총 3가지입니다.
Device 는 Free threaded 한 API 만 사용하는 인터페이스입니다.
주로 리소스들이 포함됩니다.( 버퍼나 텍스쳐, 쉐이더 등 )

Device Context 는 실제로 렌더링과 관련된 인터페이스입니다.
렌더스테이트의 교체나 Draw 명령을 내리기 위해서는
반드시 Device Context 를 통해서 커맨드를 생성해야 합니다.
더 자세한 사항은
http://vsts2010.net/115 여기를 보시기 바랍니다.^^

Device Context 는 다시 두개로 분리될 수 있습니다.
Immediate Context 와 Deferred Context 가 바로 그것들입니다.

만약 멀티스레드 기반으로 렌더링 하고 싶지 않다면,
Deferred Context 는 사용하지 않으셔도 됩니다.
Deferred Context 의 유무가 바로 멀티스레드 기반의 렌더링이냐,
아니면 일반적인 렌더링이냐를 결정
합니다.
반면에 Immediate Context 는 반드시 한개만 존재해야 합니다.
이 인터페이스는 실제로 렌더링과 관련된 커맨드를 생성하기도 하지만,
생성된 커맨드를 그래픽 카드로 보내는 일
도 합니다.

< Deferred Context >

Deferred Context는 애플리케이션에서 여러개 생성될 수 있습니다.
하나의 스레드에 하나씩 Deferred Context 가 사용될 수 있으며, 이들은 Thread unsafe 합니다.
이렇게 하나의 스레드에 할당되어진 Deferred Context는 Display List 를 생성합니다.
이들은 GPU 가 바로 처리 가능한 커맨드들을 모아둔 버퍼라고 할 수 있습니다.
이렇게 Display List 를 미리 만들어둠으로써 성능을 크게 개선 시킬 수 있습니다.
일반적으로, CPU 가 커맨드를 생성시키는 시간이 꽤 오래 걸리기 때문입니다.
( 생성될 커맨드가 변화가 없다면, 이렇게 미리 만들어 두면 크게 도움이 되겠죠? ^^ )


사실 위의 그림은 개념적인 것입니다.
실제 소스레벨에서 Deferred Context 를 가리키는 인터페이스는 별도로 존재하지 않습니다.
Immediate Context 를 가리키는 인터페이스는 ID3D11DeviceContext 입니다.
Deferred Context 를 가리키는 인터페이스도 ID3D11DeviceContext 입니다.
즉, 둘 다 동일한 인터페이스를 통해서 처리되고 있는 것입니다.
실제 멤버 변수 선언들을 조금 나열해 보면 다음과 같습니다.

ID3D11Device*      m_ipGPU;
ID3D11DeviceContext*    m_ipImmediateContext;
ID3D11DeviceContext**  m_ippDeferredContextArray;

동일한 인터페이스 선언을 확인하셨습니까?
하지만 인터페이스가 동일하다고 해서, 이를 동일하게 생각해서는 안됩니다.
동일한 인터페이스를 사용하는 이유는
Deferred Context 는 Immediate Context 의 모든 기능을 지원한다는 의미로 받아들여야 합니다.
결과적으로 Device Context 는 아래의 그림과 같은 구조로 확장될 수 있습니다.




멀티스레드 기반으로 렌더링을 한다는 것은 엄밀히 말해서는 지원하지 않습니다.
정확히 말하자면, 멀티스레드 기반으로 커맨드를 생성해서
이들을 순차적으로 그래픽 카드로 보냅니다.

위의 그림이 이를 잘 표현하고 있습니다.

Deferred Context 는 각각의 스레드에 의해서 DisplayList 를 생성하고,
이들을 그래픽 카드에 보내기 위해 버퍼에 저장합니다.
그리고 실제로 그래픽카드에 커맨드를 보내기 위해서는
반드시 Immediate Context 를 통해야 합니다.
이때 Immediate Context 를 통해서 직접적으로 커맨드를 생성시킬 수 있습니다.

아무래도 렌더링이라는 작업은 순간순간의 렌더링 상태들에 의해서
결과가 변하기 때문에, 최종적으로 전송하는 작업만큼은 순차적으로 설계한 듯 합니다.
이로써 우리는 Deferred Context 를 사용할 준비가 되었습니다.^^



[JumpToDX11-6] 커맨드(Command)...

DirectX 11 2009. 11. 9. 15:00 Posted by 알 수 없는 사용자


앞서 제 개인적인 판단에 DirectX11 의 큰 특징을 3가지 언급했었습니다.
( 테셀레이션, Compute Shader, Multi-threaded-rendering )
저는 이 세가지 중에서 멀티스레드 기반의 렌더링에 대해서
앞으로의 시간동안 글을 전개해 나갈 생각입니다.


< 커맨드를 생성하는 일 >


혹시 '커맨드(Command)' 라는 개념에 대해서 기억이 나시나요?
기억이 나지 않으신다면,
 [JumpToDX11-2]DeviceContext...넌 누구냣!! 편을 다시 읽어보시기 바랍니다.
요약을 해보자면,
API 를 통한 호출은 결국 하드웨어가 인식할 수 있는 커맨드 형태로 전달되어지게 됩니다.



지난 세대의 DirectX 는 이 모든 처리를 하나의 인터페이스를 통해서 처리했었습니다.
즉, 커맨드를 생성할 수 있는 인터페이스가 오직 하나였습니다.
그리고 그렇게 저장된 커맨드들을 그래픽카드는 순차적으로 실행만 합니다.

이를 멀티스레드 기반으로 처리하기 위해서는 사실 굉장한 노력을 해야합니다.
더 어려운 것은 멀티스레드 기반으로 처리 노력을 기울인다고 해도,
성능 향상에 대한 보장은 장담할 수 없습니다.
일반적으로 로직처리는 멀티스레드 기반으로 분산해서 처리하고는 있지만,
렌더링과 관련된 부분은 이러한 처리가 굉장히 어렵습니다.
( 렌더 스레드의 실행 중간에 렌더링 스테이트가 변하면 문제가 크겠죠? )

그래서 지난 세대의 DirectX 는 이러한 커맨드를 생성하는 부분은
단, 하나의 경로를 통해서만 가능했습니다.
그 동안 우리가 사용했던 IDirect3DDevice9 같은 인터페이스가 바로 이러한 역활을 했었습니다.
이 인터페이스는 실제로 API 를 통해서 하드웨어에게 명령 수행을 지시한다는 의미보다는,
API 를 하드웨어가 이해할 수 있는 커맨드로 변환해 주는 것에 더 가깝습니다.
그리고 그 커맨드를 통해서, 실제로 하드웨어가 실행
을 할 것입니다.

그런데 바로 이 커맨드를 생성하는 일, 누가 해주는 것일까요?
하드웨어가 이해할 수 있는 커맨드들은 드라이버( Driver )가 알고 있습니다.
드라이버는 Core API 나 런타임과 통신을 합니다.

"텍스쳐를 로딩해주세요~"
"메모리를 생성해주세요~"
"렌더링 스테이트를 설정해 주세요~"
"비디오 메모리에 리소스를 바인딩 시켜주세요~"

뭐 이런 식으로 API 를 사용하면,
이들과 관련된 커맨드를 생성하기 위해서 누군가 바쁘게 움직여줘야 할 것입니다.
그것은 바로 'CPU'
겠죠?

실제로 우리가 생성하는 커맨드들 이외에도 처리에 필요하면 커맨드가 더 많이 생성될 수도 있습니다.
예를 들면, 비디오 메모리가 가득찬 상태에서 어떤 리소스를 로드한다면
상황에 맞게 특정 리소스를 비디오 메모리에서 제거해야 합니다.
결국 커맨드들의 실행 중간에,
DirectX 의 리소스 매니져에 이를 요구할 수 있는 커맨드들이 생겨져서 더 붙여질 수도 있습니다.
만약 이런 경우라면, 처리 시간이 더 길어지게 되며,
뒤에 있는 커맨드들의 대기시간도 더 길어지게 됩니다.
전체적으로 작업 시간이 지연되는 것이죠.



< 멀티코어의 시대 >

바야흐로 멀티코어시대의 시대입니다.
이제는 CPU 의 성능적인 발전은 정체되었고,
PC 에 탑재되는 CPU 의 갯수가 성능을 좌우하는 시대입니다.

지금까지의 DirectX 는 싱글코어 기반으로 설계되었다고 지난 회에 언급했었습니다.
CPU 의 성능 발전이 지속적으로 상승 곡선을 그렸다면,
아마 렌더링을 멀티스레드로 할 위험(?)은 피할 수 있었을지도 모릅니다.^^

그 동안 DirectX 팀이 최적화 작업을 한다는 것은
API 호출에 대한 오버헤드를 줄이는 것이 가장 큰 일 중에 하나였습니다.
되도록이면 적은 CPU 사이클을 통해서 커맨드를 실행하게 하려고,
정말이지 많은 노력들을 해왔습니다.

그런데 CPU 가 여러개 탑재되고, GPU 가 발전하면서
놀고 있는 CPU 가 생겨나기 시작했고,
GPU 도 많은 시간을 놀면서 지내기 시작했습니다.
그래서 이들에 대한 활용에 대안으로 등장한 것이 바로
멀티 스레드 기반의 렌더링 작업과 Compute Shader 입니다.
멀티스레드 기반의 렌더링은 CPU 에게 렌더링 작업을 분산시키는 것이고,
Compute Shader 는 GPU 를 CPU 처럼 활용하는 것입니다.

제가 앞으로 언급할 것이 바로 멀티스레드 기반으로 렌더링하는 것입니다.
즉, CPU를 활용하는 것으로 볼 수 있습니다.
앞서 렌더링을 멀티스레드로 하는 것은 굉장히 위험한 일이라고 제가 언급했었는데,
이것이 어떻게 가능하냐구요?
네, 맞습니다.
사실 이것은 틀린 말입니다.
정확히는 커맨드를 멀티스레드 기반으로 생성하는 것이 
바로 멀티스레드 기반의 렌더링의 핵심
입니다.


< 다음 회에는... >
이번 시간에 커맨드에 대한 개념을 확실히 잡으셨는지 모르겠습니다.
다음 회 부터는 멀티스레드여서 행복(?)한 부분들을 하나씩 살펴보겠습니다.^^


 

[JumpToDX11-5] 새로운 시대를 여는 DirectX11...

DirectX 11 2009. 11. 2. 15:00 Posted by 알 수 없는 사용자


한주만 쉰다는 것이, 죄송스럽게도 긴 휴식을 가지고 다시 등장습니다.
지난 시간까지 DirectX11 의 기본 API 를 간단히 언급했었습니다.
쉬는 사이에 안승근님께서 DirectX11과 관련된 기본적인 API 에 대한 글을 작성하기 시작하셨기 때문에
앞으로 기본적인 API 위주로 내용을 언급하지 않습니다.


< DirectX9 까지의 특징 >

DirectX는 Windows95 운영체제와 함께 처음 공개된 후에, 
어느덧 현세대까지 발전을 거듭했습니다.( 세월 참 빠르죠? ^^ )

너무 오랜 시간 전은 저도 잘 몰라서 DirectX7 버전부터의 가장 큰 변화를 하나씩 언급해 보겠습니다.
DirectX7 버전부터 변환과 라이팅(T&L) 을 위한 GPU가 활용되기 시작했고,
DirectX8 버전부터는 'Shader' 라는 GPU 를 활용한 프로그래밍이 도입되어서
현재 가장 개발자에게 주목받는 영역이 되었습니다.
개인적인 견해차이가 있겠지만, 저는 DirectX9 까지의 발전 과정 중에
가장 큰 변화로 바로 이 'GPU 의 활용'
이라고 생각하고 있습니다.

그러면 DirectX9 까지의 발전에서 변심(?)하지 않고,
저희를 언제나 반갑게(?) 맞이해 주었던 부분은 어떤 것이 있을까요? ^^
그것은 바로 API 를 설계할 때 항상 싱글 코어를 고려하고 만들었다는 것입니다.

또 다른 부분은 API 자체가 GPU 의 정점 처리 기능을 규정하고 있다는 것입니다.
언제나 '정점입력-->래스터라이즈-->픽셀처리-->디스플레이' 라는 큰 단계를
API 레벨에서 정의하고 있었습니다.
그 동안 우리는 이것은 Fixed pipeline 이라고 불렀습니다.
아래 이미지는 DirectX8 & 9 의 파이프라인입니다.



이미지 출처 : http://pc.watch.impress.co.jp/docs/column/kaigai/20090804_306876.html

사실 DirectX8 & 9 는 크게 차이가 없습니다.
파이프라인상에서 굳이 찾아야 한다면, 텍스쳐 메모리를 버텍스 쉐이더 단계에서도
참조할 수 있다는 정도일 뿐입니다.

간단히 제가 하고 싶은 말을 정리해 보자면,
'싱글코어 기반의 DirectX 의 시대는 이제 역사의 뒤로 사라지게 될 것이며,
GPU 는 더욱 복잡한 기능을 요구하게 될 것이다'
정도로 정리하겠습니다.
( 예언은 아니고, 이미 이렇게 되고 있는 상황이죠..^^ )


< 새로운 시대를 여는 DirectX11 >

아래는 DirectX11 의 파이프라인입니다.
잘 보시라고 그냥 크게 띄웁니다..^^


이미지 출처 : http://pc.watch.impress.co.jp/docs/column/kaigai/20090804_306876.html


DirectX11 의 가장 큰 특징을 저는 크게 3가지로 나누어 보았습니다.
  • GPU Tessellation.
  • Compute Shader.
  • Multi-threaded rendering.

사실 DirectX11 의 많은 부분은 X-Box360 에서 이미 사용되고 있습니다.
X-Box360 의 ComputeShader 지원은 모르겠으나, 나머지 두가지는 지원하고 있습니다.
X-360을 언급한 이유는 이들 기능이 이미 어느 정도 검증을 받은 기능이라는 점을 강조하고 싶어서 입니다.
( 물론 최신 버전이기 때문에 더 빨라지고, 더 좋아진 부분이 많습니다.^^ )

DirectX11 의 큰 패러다임은 '놀지마' 입니다.
이제는 멀티코어(CPU)와 GPU에게 최대한 많은 일을 시킬 수 있는 구조로
하드웨어를 구성했고, 그것을 기반으로 해서 런타임과 API 를 설계
하고 만들었습니다.

DirectX9 까지는 API 가 변화를 주도했다면,
이제는 DirectX API 변화를 하드웨어가 주도하고 있다고 볼 수 있습니다.
그러다보니 자연스럽게 API 도 더욱 하드웨어에 가깝게 설계되었습니다.
대표적으로 OutputMerge 를 지칭하는 OMxxxx 계열과
InputAssembler 를 지칭하는 IAxxxx 계열 등이 있습니다.

혹시 DirectX8-->9 로 포팅 작업을 하셨던 분들이 이 글을 읽으시는지 모르겠습니다만,
8-->9 의 변화는 API 차원에서 변화가 컸기 때문에 매우 단순했습니다.
하지만 이제는 하드웨어가 크게 변했기 때문에,
단순 포팅 작업 정도로 생각하시면 큰 오산입니다.
물론 단순히 API 만 교체해도 성능 향상을 얻을 수 있습니다.
DirectX11 은 하드웨어 오버헤드를 줄이기 위해 많은 최적화 작업을 수행했다고 합니다.

새로운 DirectX 의 시대가 왔다는 느낌이 드시나요? ^^

'DirectX 11' 카테고리의 다른 글

[DX11_#4]텍스트, 버튼 출력  (0) 2009.11.10
[JumpToDX11-6] 커맨드(Command)...  (0) 2009.11.09
[DX11_#3]기본적인 설정  (0) 2009.10.22
[DX11_#2]D3D Buffer( 2 / 2 )  (0) 2009.10.13
[DX11_#1]D3D Buffer( 1 / 2 )  (0) 2009.09.22

Welcome to dynamic C# 외전(1) - Generate From Usage.

C# 2009. 10. 25. 09:00 Posted by 알 수 없는 사용자

- 베타2를 맞이하여.

비주얼스튜디오 2010 베타2가 드디어 나왔습니다. 모양도 초큼더 이뻐진거 같구요, 이제 슬슬 제품이 출시될거 같다는 느낌도 드는 군요. 제가 처음 비주얼 스튜디오를 접한게 비주얼스튜디오2002 베타2 버전이었는데요, 왠지 향수가 느껴지네요.-_-;;; 이번 포스트에서는 TDD의 대세를 따라서 코딩을 좀더 편리하게 해주는 기능하나를 소개해드리려 합니다.


- 이름하여 Generate From Usage!

모 이름은 '사용하는 모냥을 봐서 생성하겠다'정도가 되겠네요. 2008까지는 TDD방식으로 개발을 한다고 해도, 클래스등을 미리 만들어 놓고, 메서드 수준에 가서야 메서드 스텁은 생성하면서 TDD방식을 적용할 수 있었습니다. 물론, 편리한 툴의 지원을 받는 면에서 말이죠. 그런데 2010 베타2 부터는 TDD를 편리하게 할 수 있도록 좀 더 멋진기능이 지원됩니다. 한번 살펴보시져!


예들 들어서, Test123이라는 클래스를 TDD로 만들려고 합니다. 그러면, Test123은 당연히 현재 존재하지 않는 클래스이겠죠? TDD가 일반적으로 시나리오를 기반으로 테스트케이스를 먼저 만들고, 그 테스트를 통과하도록 구체적으로 코드를 작성해나가는 방식이니까요. 약간 귀찮은 문제가 여기서 발생합니다. 실제로 TDD를 해보면, 테스트 코드를 작성할때 대상이 되는 클래스를 열심히 타이핑하는데, 기존에 없는 클래스기 때문에 당연히 인텔리센스의 지원이 안되서 날코딩을 해야 하는거죠. 그래서 귀찮으니깐 없는 클래스를 껍데기만 미리 작성해놓고, 인텔리센스의 지원을 받습니다. 그리고 VS2008에서는 스텁생성이 메서드레벨에서만 지원됐기 때문에, 클래스를 선언해놔야 좀더 편리하기 때문이죠.

근데, 만약에 존재하지 않는 클래스라도 인텔리센스의 지원을 받을 수 있다면? 그리고 그 클래스의 스텁을 생성해줌과 동시에, 클래스 파일까지도 생성을 해준다면? 그리고 드라군이 출동한다면?? ........ 아무튼 *라게 많이 편하겠죠?

<그림1>을 보시면, 이런 멋진 기능이 이제 현실로 다가왔음을 느끼실 수 있습니다. 분명히 Test123은 없는 클래스니깐, 빨간 밑줄이 그어졌는데, new뒤에 나오는 인텔리센스에는 Test123이 버젓이 들어가 있습니다!!!



<그림1>버젓이 들어가 있다!!!!


인텔리센스에 버젓이 들어가 있었지만, 아직 정의안된 클래스니깐 <그림2>처럼 에러메세지가 나오는걸 보실 수 있습니다.


<그림2>클래스정의가 엄서요!!


하지만, 예전버전에서 없는메서드에 마우스 오른쪽 버튼을 눌러서 메서드 스텁을 생성했듯이, Test123위에 마우스를 놓고 오른쪽 버튼을 눌러보면, <그림3>처럼 클래스를 생성하는 옵션이 있습니다.



<그림3>참으로 착한 옵션이로닭!!!


그리고 결과를 보면, <그림4>처럼 Test123.cs라는 파일이 생성되었고, <그림5>처럼 껍데기가 작성된 걸 보실 수 있습니다!



<그림4>조...좋은 생성이다1



<그림5>조...좋은 생성이다2

그리고 이번엔, 없는 프로퍼티를 하나 써볼까요? <그림6>처럼 아직 정의가 안된 프로퍼티를 갖다쓰면, 어쩌구 저쩌구 하고 컴파일러가 불평을 합니다.



<그림6>어쩌구 저쩌구...


그러면, 클래스와 같이 오른쪽 버튼을 지그시 눌러주면, <그림7>처럼 필드나 프로퍼티로 생성을 할 수 있습니다. 프로퍼티를 눌러보면 <그림8>과 같이 프로퍼티가 하나 추가된걸 보실 수 있죠.



<그림7>프로퍼티 하나 추가여.



<그림8>조...좋은 생성이다3


- 마치면서

VS2008에서 TDD를 아주 허접하게 해본 경험으로 미뤄볼때, 확실히 좀더 잔손질을 줄여주는 기능이 될 거 같습니다. 뭐 꼭 TDD가 아니더라도 기능을 활용할 일은 많은 거라는 생각이 드네요. 전 이래서 비주얼 스튜디오가 좋습니다. ㅋㅋㅋ....-_-;;;

[JumpToDX11-4] ID3D11View

DirectX 11 2009. 9. 7. 18:00 Posted by 알 수 없는 사용자

 

이번 회에서는 일단 소스를 좀 나열해 보겠습니다.
일단 변수들은 다음과 같습니다.




이어지는 상황은 다음과 같습니다


 

BackBuffer 를 설정했습니다. 일단 'View' 라는 키워드에 주목해 주시기 바랍니다.
그리고 다음에 이어지는 상황을 다시 보겠습니다. 

 

 




이어졌던 소스는 Depth-Stencil Buffer 생성을 위한 작업이였습니다.

역시나 낯선 개념이 등장하는데, 바로 'View' 입니다.
우리가 앞서 생성했던 BackBuffer 와 Depth-Stencil Buffer 에는 CreatexxxxxxxView() 형태로
작업을 해주고 있습니다.

하나의 뷰는 렌더링 작업 중에 파이프라인에서 접근할 수 있는 리소스 일부분을 의미합니다.

더 정확한 개념을 위해서 아래의 계층구조를 한번 살펴보시기 바랍니다.






우리가 사용하는 모든 리소스들은 사실 ID3D11Resource 를 상속받아서 구성됩니다.

텍스쳐나 각종 버퍼 등이 이에 속한다고 할 수 있습니다.

( ID3D11Buffer, ID3D11Texture )

 

ID3D11View 를 상속받아서 구현되는 것들은 ID3D11RenderTargetView, ID3D11DepthStencilView, ID3D11ShaderResourceView 가 있습니다.

 

나열하고 보니깐 약간 감이 오시지 않으십니까?

이렇게 분리가 되었는데, 사실 ID3D11View ID3D11View::GetResource() 라는 멤버함수를 가지고 있습니다.

 

결국 ID3D11View ID3D11Resource 와 개념적으로 메모리 데이터는 동일하다고 볼 수 있습니다.

그러다 보니 이 두가지 인터페이스를 구별해서 설명하기가 무척 난해합니다.
비슷하면서도 실질적으로 수행되는 역활에는 엄연한 구분이 있으니 말이죠...

 

이렇게 분리함으로써 역할 구분이 명확해서 코드의 품질이 향상되었다라고 말할 수 있습니다.
조금 더 좋은 방향으로 생각해 본다면,
아마도 내부적으로 조금 더 최적화 된 위치에 메모리를 할당해 주지 않을까? 라는 의심도 해봅니다.
( 왜 그런지 이유를 꽤 오래 생각했지만, 답을 찾지 못했습니다..T.T )

 

 

참고로 얘기드리면,

DirectX9 버전까지 유용하게 사용되던 메모리 풀의 개념이 이제는 CPU 에서 읽기/쓰기 작업,
GPU
에서 읽기/쓰기 작업이 가능여부를 설정하는 개념형태로 변경
되었습니다.

이것에 대한 얘기는 다음 번에 저나 다른 분이 해주실 겁니다.

( DirectX11 파트에는 저 말고도 한분이 더 계십니다…^^ )

 

위의 코드에서 View 계열들은 GPU 만 읽기/쓰기 작업이 가능한 형태로 그래픽 카드상에
메모리를 할당했습니다.


결국 위의 작업은 바로 아래에 나오는 작업을 위해서 필요했던 것입니다.



보시듯이 모두 View 계열의 인터페이스를 설정했습니다.



< 마치면서... >
다음주는 한주 쉬게 될 것입니다.
스터디 내부 발표가 있어서...쿨럭~



 

[JumpToDX11-2]DeviceContext...넌 누구냣!!

DirectX 11 2009. 8. 24. 14:00 Posted by 알 수 없는 사용자



지난 회에서 DXGI 에 대해서 잠깐 살펴보았습니다.
DXGI 에 대한 사용방법은 여기서 언급하지 않습니다.
왜냐하면 제가 진행할 코딩에서는 기본적으로 셋팅되어 있는 그래픽 카드를 사용하는 것을 전제로
진행할 것이기 때문입니다.

혹시 호기심이 더 왕성하신 분들은 IDXGIFactory 인터페이스를 살펴보시면 됩니다.
멤버 함수중에 MakeWindowAssociation, EnumAdapters 정도 살펴보시면 도움이 될 것입니다.
( API 함수 이름만 봐도 느낌이 팍팍! )

예상하시겠지만, DXGI는 연결가능한 장치(어댑터)들을 나열해서
그것 중에 하나 선택하는 역활이 필요합니다.
저는 기본적으로 설정된 어댑터를 사용할 것이기 때문에 이들에 대해서는 언급하지 않겠습니다.
 DXGI 계열의 API들도 양이 상당합니다.( 그래서 일단 패스~ )


지난 회에 언급했던 디바이스 초기화를 위한 변수들 기억하시나요?
다시 나열해 보면 아래와 같습니다.




< IDXGISwapChain >

가장 먼저  IDXGISwapChain 에 대해서 살펴봐야하겠지만, 이것에 대한 별도의 설명이 필요할까요?
Front Buffer( 현재 화면에 보여지는 버퍼 )와 Back Buffer( 현재 연산을 해서 기록하는 버퍼 ) 를
준비해서 이것을 Flip 시키면서 번갈아 가면서 보여주는 것을 의미합니다.
( 너무 고전적인 내용이라 더 설명하면 혼날듯...)

우리가 렌더링할 영역(버퍼)에 대한 포맷과 같은 각종 속성들을 설정해 주어서 생성을 요구하고,
포인터를 받으면, 이들 버퍼에 대한 정보를 제어
할 수 있습니다.
나중에 살펴보게 되겠지만, Present() 라는 API 를 기억하시나요?
9.0 에서는 이것이 ID3DDevice9의 멤버함수로써 사용했었습니다.
하지만 현재는 IDXGISwapChain 의 멤버함수로 등록되어 잇습니다.
그래서 이에 대한 포인터가 필요합니다.^^
결론적으로 얘기 드리면 앞으로 화면 출력에 관한 모든 것은 IDXGI 계열의 인터페이스로서 제어할 수 있습니다.





아마 위와 같은 형식이겠죠? ( 각각의 성분에 대한 설명은 생략합니다...저걸 다 어찌 설명해요..-_- )

 

 

 < DeviceContext...넌 누구냣!! >

이상한 인터페이스가 DirectX11 에서 생겼습니다.
Device는 무엇인지 알겠는데, DeviceContext 는 또 무엇일까요?
사실 이것은 그동안 Device 인터페이스들이 해오던 역활을 두가지로 분리한 것에 지나지 않습니다.

즉, ID3D11Deivce 는 주로 리소스( 버퍼나 텍스쳐 등 )의 생성에 대한 인터페이스이며,
ID3D11DeviceContext 는  이들 리소스를 제어하고 관리하기 위한 인터페이스입니다.

그렇다면 왜 이렇게 두 가지로 분리된 것일까요?
먼저 아래의 그림을 살펴보겠습니다.




우리가 렌더링을 수행하기 위해서는 애플리케이션에서는 관련 Core API 와 Runtime을 사용하게 됩니다.
이들 Core API 와 Runtime 은 우리가 필요한 렌더링에 관한 모든 것을 수행합니다.
메모리 할당이나 리소스들의 수정, 메모리 바인딩, 각종 렌더링 스테이트의 제어 등등 굉장히 많죠.
( 물론 쉐이더 코드들을 통해서도 이들을 제어할 수 있는 부분이 있습니다만,
  여기서는 흐름상 고려하지는 않습니다.  ) 

DirectX 시스템은 Application 과의 오버헤드를 최소화 하기 위해서
이들 사이를 매우 얇은 추상화 단계로 디자인 했었습니다.
즉, Core API 나 Runtime 들은 바로 Driver 에 접근할 수 있었습니다.

그래도 약간(?) 존재해 있는 Application 과 하드웨어간의 오버헤드를 줄이기 위해서
기존의 Device 의 역활을 Device 와 DeviceContext 로 분리
하게 된 것입니다. 

그렇다면 여기서 발생되는 오버헤드란 것은 어떤 것일까요?( 의문에 의문 연속입니다..-_- )
우리가 사용하는 각종 API 들은 Runtime 에 전달되어서 하드웨어가 인식할 수 있는
커맨드( Command ) 들로 변환
됩니다.

Runtime 은 이들 커맨드들을 담을 수 있는 메모리 공간을 가지고 있어서, 커맨드들을 저장하게 됩니다.
그러다가 이들 버퍼가 가득차거나, 혹은 렌더링 데이터의 업데이트가 필요한 경우에
이들을 하드웨어로 전송하게 되는 것입니다.
바로 이 커맨드들에 대해서 오버헤드가 발생하는 것입니다.
이 커맨드들이 오버헤드를 발생시키는 이유는 여러가지가 있었습니다.
하드웨어의 경우에는 프로세싱( processing ) 스타일이 매우 다양하기도 했고,
API 와 하드웨어 상에서 커맨드 전달이 잘못 전달되는 경우도 있었다고 합니다.
( 아무래도 하드웨어가 너무 다양해서가 주된 이유였던 듯 합니다. )

이들에 대한 오버헤드를 줄이는 방법을 고민하던 중에 나온 결과물 중에 하나가
바로 'DeviceContext' 라는 것입니다.
( 뒤에 언급할 기회가 있겠지만, 'State Object' 가 바로 이 오버헤드를 줄이기 위해 등장한 개념이기도 합니다. )

Device 의 경우에는 오버헤드를 줄이기 위해 등장한 개념이
리소스의 생성/해제를 담당하는 커맨드들과 그 리소스들을 제어하는 커맨드들로 분리하는 것입니다.

 

분리함으로써 어떤 성능 향상이 있었을까요?
리소스의 생성과 해제는 사실 멀티스레드 형태의 API 호출에도 별 문제가 없습니다.
어차피 명령어들이 큐 형태로 쌓이게 될테니까요.
반면에 렌더링 커맨드들은 멀티스레드 형식으로 구성되면 큰일 나겠죠?

결국 Device 는 Free threaded 형식으로 구성되었고,
DeviceContext 는 그렇지 않다는 것
입니다.
Free threaded 형식으로 구성되었다는 것은 스레드에 안정성을 유지하기 위한
별도의 lock/unlock 작업이 필요없다는 것입니다.
멀티스레드에 안정적이라는 얘기는 스레드 세이프하다는 것입니다.

(정확하게 확신은 아직 드릴 수 없지만, 멀티스레드 관련 렌더링과도 관련이 있는 부분이 여기이지 않을까요.)

사실 리소스의 생성과 해제가 성능에 많은 부분을 차지한다고 볼때,
이렇게 분리되어진 것을 환영해야 할 것입니다.

 

 < 다음 회에는... >

글이 좀 길어지는 것 같아서 일단 여기서 마무리 합니다.
다음 회에는 나머지 초기화 부분에 대해서 계속 언급하겠습니다.^^

 





 

'DirectX 11' 카테고리의 다른 글

[DX11_#2]D3D Buffer( 2 / 2 )  (0) 2009.10.13
[DX11_#1]D3D Buffer( 1 / 2 )  (0) 2009.09.22
[JumpToDX11-4] ID3D11View  (0) 2009.09.07
[JumpToDX11-3] Feature Level  (0) 2009.08.31
[JumpToDX11-1] 사라진 Direct3D 오브젝트를 찾아서...  (8) 2009.08.17

[JumpToDX11-1] 사라진 Direct3D 오브젝트를 찾아서...

DirectX 11 2009. 8. 17. 14:00 Posted by 알 수 없는 사용자

< 인사 및 소개 >

안녕하세요.
저는 이번에 vsts2010 에 참여하게 된 조진현 이라고 합니다.

어떤 주제에 대해서 글을 쓰다는 것은 무척 어려운 일입니다.

그렇기 때문에, 이 스터디 참가를 굉장히 망설이기도 했습니다.
많은 분들과 함께 열정을 가지고 참가를 결심했고, 드디어 처음으로 글을 남기게 되었습니다.
제가 가장 우려하는 것은 잘못된 지식을 전달하는 것입니다.
그래서 조심스러운 마음으로 글을 작성할 것입니다.
잘못된 부분이나 미흡한 부분이 있으면, 바로 지적해주시면 감사하겠습니다.

제가 언급할 큰 주제는 DirectX 11 과 관련이 있습니다.
그 중에서도 멀티 코어를 활용한 DirectX 사용에 초점을 두고 글을 전개할 생각입니다.
글의 주요 대상은 DirectX9 를 사용하시다가 DirectX11 을 사용하고자 하시는 분들입니다.

일단 방대한 변화에 대해서 모두 나열하기는 힘듭니다.

그래서 간단히 제가 코딩을 하면서 필요했던 API 위주로 살펴보면서 변화를 언급하고자 합니다.
그런데 하나 문제가 있습니다.
현재 DirectX 11 은 하드웨어 가속이 지원되지 않습니다.
오직 REF 모드로만 작동을 합니다.
아마도 아직 정식으로 widnows 7 이 출시가 이루어지지 않아서 그런 듯 합니다.
이점, 꼭 주의하시기 바랍니다.
괜히 DirectX 11 예제 실행했다가, 실행 성능이 떨어진다고 컴퓨터를 부수는 행위는 자제해 주세요.^^


< 사라진 Direct3D 오브젝트를 찾아서... >

우리가 가장 먼저 접하게 되는 DirectX 의 API 는 CreateDevice() 일 것입니다.
사실 이전 버전까지는 CreateDevice() 에 대해서 별도로 언급할 내용이 없었을 것이지만,
늘(?) 그렇듯이 DirectX 의 변화를 설명해주는 API 가 바로 CreateDevice() 입니다.
일단 CreateDevice() 를 위한 관련 변수들부터 봐야겠죠?
 



잠깐!!
가장 먼저 헤더 파일들을 살펴보는게 순서이죠.

헤더는 다음과 같이 변경되었습니다.
굳이 헤더의 용도에 대해서 일일이 나열하지는 않았습니다.

// Direct3D11 includes
#include <dxgi.h>
#include <d3d11.h>
#include <d3dCompiler.h>
#include <d3dx11.h>
#include <dxerr.h>

 

라이브러리 링크는 아래의 것들을 해주시면 됩니다.

#pragma comment( lib, "dxguid.lib" )
#pragma comment( lib, "d3dcompiler.lib" )
#pragma comment( lib, "dxerr.lib" )
#pragma comment( lib, "dxgi.lib" )
#pragma comment( lib, "d3d11.lib" )
#pragma comment( lib, "d3dx11.lib" )




변수들을 나열해 보겠습니다.




 생소한 부분이 눈에 보이시나요?
 'ID3D11DeviceContext' 라는 것이 새롭게 등장했습니다. ( 다음 번에 언급할 것입니다. )
 그리고 Direct3D 인터페이스가 사라진 것을 찾으셨습니까?




위의 그림은 DirectX 9 의 아키텍쳐입니다.
우리가 작성하는 프로그램은 오직 Direct3D 나 GDI 를 통해서 저수준의 하드웨어와 통신을 할 수 있었습니다.

그런데 현재의 DirectX 아키텍쳐는 아래와 같습니다.



 여기서 또 하나 생소한 것이 등장했습니다.
바로 DXGI ( DirectX Graphics Infrastructure ) 입니다.
"DirectX9 에서 사라진 'Direct3D 오브젝트'를 'DXGI' 가 대체하는게 아닐까?" 라는 의문이 들었다면,
박수를 보내드리고 싶습니다.( 브라보~~ )


네, 맞습니다.
'DXGI' 라는 것이 바로 사라진 'Direct3D 오브젝트' 입니다.
'Direct3D 오브젝트' 의 역활에 대해서 혹시 기억하십니까?
하드웨어와 연결된 디바이스들을 나열하고, 모니터로 출력되는 결과들을 관리해주기도 했었습니다.
우리가 관리하기 힘든 저 수준의 작업들을 바로 이 'Direct3D 오브젝트'가 했었습니다.
그런데 이제는 이것을 'DXGI' 가 해주고 있습니다.
( IDXGISwapChain 보이시나요? 이것도 다음 회에 언급하겠습니다. )
 

아키텍쳐 구조를 보시면 아시겠지만, DirectX9 까지는 일반 애플리케이션에서 DirectX API 를 통하지 않고는
DirectX 를 사용할 수 없었습니다.
그런데 최근에는 일반 애플리케이션은 모두 DXGI 를 통해서 DirectX 를 사용하고 있습니다.
( 저만 놀라운 것은 아니겠죠? +_+ )
마이크로소프트에서도 강조하고 있는 사실 중에 하나가 바로 DirectX 는 더 이상 게임만을 위한 것이 아니라는 것입니다.
이제 사라진 줄 알았던 'Direct3D 오브젝트' 가 DXGI 라는 사실을 알았습니다.
앞으로 저수준의 작업이 필요하면 DXGI 를 직접 제어하거나 DirectX API 를 이용하셔도 됩니다.


< 다음 회에는... >

다음 번에는 실제로 DirectX API 를 이용한 초기화 작업에 대해서 다루고자 합니다.
즉, 우리가 앞서 선언했던 변수들에 대한 이야기를 하겠습니다.

'DirectX 11' 카테고리의 다른 글

[DX11_#2]D3D Buffer( 2 / 2 )  (0) 2009.10.13
[DX11_#1]D3D Buffer( 1 / 2 )  (0) 2009.09.22
[JumpToDX11-4] ID3D11View  (0) 2009.09.07
[JumpToDX11-3] Feature Level  (0) 2009.08.31
[JumpToDX11-2]DeviceContext...넌 누구냣!!  (1) 2009.08.24

Welcome to F#(9) - 메이져 데뷰.

F# 2009. 6. 12. 16:25 Posted by 알 수 없는 사용자
-뒷북이냐

어느덧 비주얼스튜디오 2010 베타1이 나온지도 거의 한달이 다되어 가네요. 그동안 뭐가 바뀌었는지 간략한 소개도 못드렸었군요. 뒷북이라 느끼실 수도 있겠지만, 간략하게 비주얼스튜디오 2010 베타1에서 F#이 어떻게 무명시절의 설움을 딛고 일어서고 있는지 소개해드리려고 합니다.




-메이저데뷰

개인적으로 가장 중요하다고 생각하는 점은 F#이 무명시절의 설움을 딛고 메이져데뷰를 했다는 거죠. 이제 당당하게 비주얼 스튜디오 시작시에 나오는 스플래시 화면에도 이름을 올리고, 비주얼 스튜디오를 깔고 처음실행하면 나오는 기본개발환경설정 선택창에서도 Visual F#을 보실 수 있습니다.




캬. 그리고 새 프로젝트를 눌러서 들어가보면 Visual F#이 메인에 나오고요 C#과 VB.NET은 "Other Languages" 카테고리로 분류가 됩니다. 좋네요. 참고로 F# Interactive도 기본으로 뜹니다. 


그리고 비주얼 스튜디오 2010 베타1에 포함된 F#은 약간 버전업이 되었는데요(1.9.6.2 -> 1.9.6.16) 아래 그림을 비교해보시면, F#의 버전과 닷넷프레임워크 버전이 바뀌었음을 확인해볼 수 있습니다.

(2008)
(2010)


그리고 이번버전부터 PowerPack을 따로 받아서 깔도록 바뀌었습니다. 그래서 F# Interactive에서 #r 해서 PowerPack.dll을 로드하려고 해도 dll을 찾아오지를 못하는데요, 그래서 따로 다운을 받아서 복사를 해줘야 합니다.  여기에서 받을 수 있구요~ "C:\Program Files\Microsoft F#\v4.0" 이 경로에 복사해서 넣어주면, F# Interactive에서 기존처럼 #r "FSharp.PowerPack.dll";; 구문으로 추가할때도 자동으로 찾아서 추가해줄 수 있습니다. 그리고 기존처럼 비주얼스튜디오 2008에서도 베타1에 추가된 1.9.6.16버전을 사용할 수 있는데요, 여기에서 다운받으실 수 있습니다.


그동안 6개월동안 커뮤니티의 피드백을 받아서 F#언어와 컴파일러의 버그를 잡고 구조와 성능을 개선하는데 집중했다고 합니다. #light가 이제는 기본으로 설정되는 것과 .NET 4.0의 BingInteger와 연동이 잘되고, params타입을 사용하는 메서드를 호출하거나 만들수있게 되었고, 라이브러리의 이름이나 표현을 표준에 맞게 수정하면서 타입파라미터가 대문자로 바뀌는 등의 변화가 있었습니다.


(소문자였던 타입 파라미터가)

(대문자로 바뀌었음)



-이게 다야?

사실, 더 자세하게 하나하나 분석해드릴 수 있으면 좋으련만, 공부한지 얼마 안되는지라 뭐가 자세하게 바뀐건지 감은 잡혀도 확실하게 설명드리지 못하는 점이 조금은 죄송스럽군요;;;
여기에서 추가되거나 바뀐 내용들을 자세하게 보실 수 있습니다.

F#이 도대체 왜 비주얼스튜디오에 정식으로 추가된 걸까요? 기존에도 J#등과 같은 언어가 추가되었다가 소리소문없이 사라지기도 했었습니다만, F#도 그런걸까요? 사실 저는 함수형언어에 기존의 언어들이 갖지 못한 장점들이 있고 C#이나 VB.NET이 멀티패러다임을 지향하면서 함수형,동적 언어들의 장점을 취합하고 있지만 함수형언어 고유의 영역을 제대로 커버하는건 힘든게 아닌가 싶었습니다. 그래서 F#이 추가되는 걸 그런 점에서 봤었습니다만, 스터디를 이끌고 계시는 K님의 말씀을 듣던 중 새로운 점을 하나 발견하게 됐습니다.

패션쇼를 예를 들어주셨는데요, 제대로 옮기는지는 확실치 않지만 대략 '패션쇼에서 독특한 옷들 입고 나와서 모델들이 걸어다닌다고 해서 그 옷이 바로 백화점이나 옷가게 진열장에 걸리는건 아니다, 앞으로의 가능성과 방향을 제시하는 의미가 있는거다' 같은 말씀이였습니다. 그리고 함수형언어가 그런면이 있어서 그동안 함수형언어의 발전적인 개념들이 현업에서 쓰는 언어에 하나씩 추가되기도 하는거라고 말이죠(LINQ같이).

이 말을 듣고 나닌 Paul Graham이 왜 그토록 Lisp을 최고로 치면서 시간이 지나면 사라질 언어말고 언어계층의 뿌리에 해당하는, 그래서 시간이 지나도 가치가 변하지 않을 Lisp같은 언어에 집중하라고 말을 했는지 알것 같기도 했습니다.

F#이 메이져 데뷰를 하면서 그걸통해 닷넷프레임워크에서 돌아가고 서로간에 호환이 가능한 함수형언어를 확보하는 동시에, F#을 통해서 시험적인 요소들의 가능성도 보고 닷넷을 더 발전적인 형태로 가져가기 위한 시도가 아닌가 하는 생각이 들었습니다.

제대로 설명한건지는 확신이 안서지만 어쨌든, 기존의 함수형언어의 팬들이 F#을 통해 뭔가를 많이 시도하고 즐긴다면 닷넷이 더욱 풍성해지는 거겠죠~~~~.

-참고자료
1. http://blogs.msdn.com/dsyme/default.aspx

Welcome to Dynamic C#(2) - Wanna be a polyglot.

C# 2009. 5. 17. 16:25 Posted by 알 수 없는 사용자

- 자넨 왜 그렇게 언어에 집착하는고?

넵, 확실히 저는 언어에 쫌 집착하는 편이긴 합니다. 우리가 말하고 쓰는언어도 꽤나 집착하는 편입니다. 언어를 제대로 배우려고 노력하다보면, 더 재밌는 걸 많이 접할 수 있게 되고 그 언어뿐만 아니라 언어를 쓰는 사람들의 사고방식도 아주 조금씩 이해하게 되기 때문이죠. 뭔가 보고싶은게 있는데 그게 제가 모르는 언어로 되어 있어서 못보는건 조금 슬픈일인거 같습니다. 개인적으로 부족한 실력이지만, 미드&일드를 아주 재밌게 즐기고 있습니다.

프로그래밍 언어도 비슷한 의미에서 집착하게 되는게 아닐까 싶습니다. 프로그래밍 언어에는 그 언어를 만들고 지지하는 사람들의 사고방식도 같이 배울 수 있게 되고, 점점 재밌게 할수 있는게 늘어나기 때문이죠. 최근에 언어에 대해서 아주 부족한 의견이지만 글을 썼던 적이 있습니다. 관심있으신 분은 보시고 따쓰한 피드백 주시면 완전 감사하겠습니다. 

아무튼 그런의미에서 F#에 C#에 Axum까지 건드려보고 있는거지요. 줏대가 없다거나 바람기가 있다거나 뭐 그런건 아닙니다. 그럼 본론으로 들어가서, 지난번엔 동적C#에 대한 이야기를 조금 드렸었습니다. 하지만 정작 알고 싶은건 dynamic키워드란게 생겼고 대충 오리꽥꽥 어쩌구 저쩌구 하는건 알겠는데, 어디다 써먹는거란 말이더냐? 뭐 그런거겠죠. 그래서 쌩초보이지만, 최대한 그런관점에서 접근해보고자 합니다. 그 첫번째가 실제로 프로젝트를 하다가 하나 느낀게 있어서 그걸 적어보고자 합니다. 



- 시나리오
(제가 모르는 해결방법이 있을수도 있습니다. 그럴땐 따쓰한 피드백을!)

LINQ to SQL(이하 L2S)로 프로젝트를 진행중입니다만, 데이터가 추가되거나, 수정되거나 삭제될때 그 값들의 이전/이후 데이터를 포함해서 그 데이터의 고유번호(seq)를 같이 저장하는 뭐 그런 시나리오입니다. 그래서 L2S에서는 아래와 같은 방법을 제공합니다.

 

ChangeSet changeSet = db.GetChangeSet();

foreach (Customer c in changeSet.Inserts)
{
	.......
}

 

하지만, 위와 같은 코드는 한번의 SubmitChanges로 변경이 일어나는 대상 테이블이 하나라면 Generic파라미터로 처리할 수도 있겠지만(ChangeSet에서 리턴되는 객체의 타입이 object입니다), 주문과 상세주문같이 한번에 여러개의 테이블에 변경이 일어난다면, 그닥 친절하지 못한 시나리오가 되겠습니다. 그래서 그때 들었던 생각이 "아 이거 dynamic키워드를 이용해서 오리꽥꽥타이핑(duck typing)을 이용하면, 쫌 쉽게 될거 같은뎅..." 였습니다. 그래서 한번 살짝 구현해봤습니다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace FirstDynamic
{
    class Customer
    {
        public int Seq{get; set;}
        public string Name {get; set;}        
    }

    class Company
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class Project
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class NoneSeqThing
    {
        public string Name{get; set;}
    }

    class Logger
    {
        public void WriteLog(dynamic entity)
        {
            try{
                Console.WriteLine(entity.Seq);
            }
            catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
            {
                Console.WriteLine("Exception : " + ex.Message);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {            
            Logger logger = new Logger();

            Customer customer = new Customer
            {
                Seq = 1,
                Name = "Boram"
            };

            Company company = new Company
            {
                Seq = 6,
                Name = "NanoSoft"
            };

            Project project = new Project
            {
                Seq = 108,
                Name = ".NET 99.9"
            };

            NoneSeqThing noneSeqThing = new NoneSeqThing
            {
                Name = "None Seq Thing"
            };

            object[] entities = new object[] { customer, company, project, noneSeqThing };

            foreach (object entity in entities)
            {
                logger.WriteLog(entity);
            }
        }
    }
}

 

위에서는 몇가지 객체를 선언해서 DTO를 흉내냈고, Seq가 있는 타입과 없는 타입이 있는 것을 볼 수 있습니다. 그리고 ChangeSet에서 반환되는 객체를 그냥 dynamic으로 Logger에게 넘겨주고 있습니다. 그리고 Seq멤버변수가 있으면 남기고 없으면 안남기는 식으로 다른 처리를 해주고 있습니다. 그리고 결과는 아래와 같습니다.



그렇습니다, 이런식으로 dynamic을 이용한다면 지난 포스트에서 Paul Graham아자씨가 이야기 했던 나이들고 엄한 이모 컴파일러와 좀더 편하게 대화할 수 있는 법이죠. 써놓고 보니깐 포스트가 별거 없네요. 기분 탓이 아니라 제 내공 탓이겠죠. 여담이지만, 제가 해결한 방식은 리플렉션으로 Seq프로퍼티를 검색해서 유/무를 판별하는 방식을 이용했습니다. 확실히 손이 좀더 많이 가는 방법이죠.

이렇게 여러가지 패러다임에 익숙해지고 잘 활용할 수 있게 되면, 점점 더 빠르고 경쾌한 리듬으로 코드를 작성하는 일도 가능하지 않을까 생각해봅니다. 이제 프로그래밍을 하시는 분들도 세계화에 발맞추는 속도에 걸맞게 프로그래밍언어에 대해서도  ployglot이 되어야 하지 않을까 생각합니다. 다만, 제 생각엔 그러한 노력은 프로그래머에게 족쇄를 채우는게 아니라 오히려 더 큰 자유를 주는 일이라고 생각합니다. 그럼, 또 개발하다가 dynamic의 헬프가 필요한 순간이 오면 나누도록 하겠습니다.

여담이지만, polyglot하니깐 중학교때 "핸들 이빠이 돌려"라는 한문장으로 3개국어를 자유자재로 구사하시던 한문선생님이 떠오르는 군요. ㅋ


-참고자료
1. Pro LINQ: Language Integrated Query in C# 2008, Joseph C. Rattz, Jr. , APRESS.

Welcome to Parellel world(1) - Here comes a new challenger!

C# Parallel Programming 2009. 5. 16. 16:04 Posted by 알 수 없는 사용자

-신 캐릭터의 등장.

언제나 새로운 캐릭터의 등장은 가슴을 설레이게 하는거 같습니다. 디아블로 같은 액션 RPG도, 스타크래프트같은 전략시뮬에서도, 미연시에서...... 그리고 비주얼스튜디오에서도 말이죠. Axum은 딱히 비주얼스튜디오 2010에 포함되기로 이야기 되는 언어는 아닙니다만, 왠지 2010이나 그 이후버전에선 정식으로 편입되어서 중요한 역할을 할 것같은 느낌이 들어서 아주 조금씩 소개를 드려볼까 합니다. 물론 Welcome to Parallel world에서는 Axum만 다루진 않을 거구요 기타 다른 병렬프로그래밍에 대한 이슈들을 쌩초보의 입장에서 공부하면서 정리해보고자 합니다. 신기한게 보이면 그냥 못지나치는 성격이라 시간은 부족해지는데 일은 계속해서 늘리고 있군요. 아무튼, 관심있는분들의 많은 따쓰한 피드백을 기다리며 시작해보겠습니다. 

-Axum????

Axum은 위에서 설명드린것 처럼 딱히 아직 구체적인 계획은 없고 그저 실험적으로 개발되고 있는 새로운 언어입니다. 가이드문서에서는 아래와 같이 설명을 하고 있군요.

Writing a parallel program typically requires partitioning the solution into a number of parallel tasks. Some problems are easily amenable to parallelization because the tasks can run independently of each other. In other problems the tasks have interdependencies and require coordination. ......... With Axum, we offer a language that allows programmers to arrange coordination between components in a way that is close to their natural conception of the solution. In other words, if you can model your solution in terms of interactive components, encoding it in Axum will be straightforward, and you will likely avoid many common concurrency-related bugs. 

병렬 프로그램을 작성하려면, 프로그램을 여러개의 작은 병렬작업들로 쪼개는 작업이 필요합니다. 몇가지 문제들은 애초에 서로 독립적으로 수행될 수 있으니깐 쉽게 병렬화시킬 수 있습니다. 다른 몇가지 문제들은 서로 연관되어 있기 때문에 순서를 잘 정해줘야 합니다. .... Axum은 그러한 수행순서등을 솔루션이 원래 동작해야 하는 시나리오에 근접하게 잘 정리하도록 도와주는 새로운 언어입니다. 부연 설명을 하자면, 문제해결을 위한 솔루션을 컴포넌트들의 상호작용모델로 그려낼 수 있다면, 이런 솔루션을 Axum으로 표현하는 작업은 매우 직관적이고 쉬울 것입니다. 그래서 프로그래머들은 매우 흔히 발생하는 동시성과 관련된 버그를 피할 수 있게 되는 것이죠.


즉, 병렬프로그래밍을 지원하기 위한 새로운 DSL이라고 생각하면 될 것 같기도 하군요. Axum은 C#과 비슷한 점이 많기도 하고 틀린점도 있는데 대강정리해보면 아래와 같습니다.

-C#과 Axum이 가진 공통점은 :
      모든 C# 3.0의 람다와 LINQ쿼리 같은 표현식들
      모든 C# 3.0의 yield와 yield break같은 구문들
      메서드와 필드 정의들
      델리게이트와 이뉴머레이션 타입들 

-Axum에서 볼 수 없는 C#의 요소들
      클래스, 인터페이스와 구조체
      연산자 정의들
      프로퍼티
      상수 필드와 상수지역변수
      정적 필드와 정적 메서드 

-Axum에서만 볼 수 있는 요소들
      에이전트 와 도메인
      채널
      스키마
      네트워크
      Interleaved control flow


그렇다는 하는 군요. 아무튼, 정리해보면 'Axum은 C#과 비슷한 점도 있고 틀린점도 있으며 병렬프로그래밍을 지원하기 위해서 새롭게 실험적으로 개발되고 있는 DSL이다' 정도가 되려나요?

DSL이라는 말은 제가 붙인겁니다만, 아무튼 모냥을 보니 병렬프로그래밍이라는 부분에 특화된 모습을 보이면서 class정의는 C#, F#, Managed C++, Visual Basic.NET등의 언어를 통해서 하거나 C#을 통해 직접 정의할 수 있다는 걸로 봐서는 DSL이라고 보는게 맞는거 같기도 하군요. 여담이지만 위에서 언급한 4개의 언어의 순서는 제 맘대로 한건 아니구요 문서에 있는 순서를 그대로 언급한 겁니다. F#도 이제 MS내에서도 중요하게 생각하고 있다는 걸까요? 왠지 급흐뭇해 지는 군요.
(찾아보니 이전에 Maestro라는 코드네임으로 개발되던 언어였고 DSL이 맞군요 ㅋ)


여담2 이지만 이런 구절도 있었습니다. "Axum is a .NET language and can use libraries written in other .NET language such as C#, Visual Basic or F#." 이제 F#도 C#과 VB.NET으로 대표되는 주요언어에 포함되는 느낌이로군요 캬캬캬.

아무튼, Axum은 여기서 받으실 수 있습니다. 그리고 그 사이트에서 문서도 보실 수 있구요. 좀 더 자세한 이야기는 다음포스트로 넘기기로 할까요?

-나만 몰랐던가? concurrency와 parallel은 다른 것이다!

일단, 사전적 정의를 보자면 아래과 같습니다.

concurrent - 무언가가 시간적으로 동시에 일어나는 이미지
parallel - 무언가 동일한게 시간&공간적으로 다른곳에 존재하는 이미지

그리고 여기에 대한 좋은 설명이 있어서 참고해봤는데요, 싱글코어 CPU에서 실행되는 두개의 concurrent한 스레드는 concurrent하지만, parallel하지는 않다는 이야기이고... parallel은 멀티코어, 멀티CPU, 분산환경에서 얻을 수 있는 장점이라는 이야기더군요 즉, concurrent하다고 해서, parallel한것은 아니라는 것입니다.

 

- 참고자료

1. Axum Programmer's Guide, Microsoft Corporation
2. AXUM LANGUAGE OVERVIEW, Niklas Gustafsson
3. http://blogs.sun.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming


Welcome to F#(8) - 은총알과 엄친아.

F# 2009. 5. 10. 20:56 Posted by 알 수 없는 사용자
-넌 제목이 왜 맨날 이 모냥이냐.

은총알과 엄친아. 과연 전 무슨생각으로 제목을 맨날 이렇게 짓는 걸까요? 개인적으로 포스트에서 이야기 하고자 하는걸 비유적으로 설명하는걸 좋아합니다. 그래서 일까요? 늘 글을 쓰기 전에 이야기 하고자 하는 내용을 심사숙고합니다. 그렇게 해서 나오는게 고작 요정도 인거죠.

은총알. 은초딩도 아니고 이건 뭘까요? 들어보신분들도 많으시겠지만, 소프트웨어 공학에서 이야기하는 모든 문제가 이거하나면 해결된다고 하는 그런 어떤 경우에도 쓸 수 있는 만능의 해결책? 그정도 느낌을 생각하시면 될거 같습니다. 즉, 많은 사람들을 파닥파닥 낚이게 만드는 주범이지요. 엄친아도 못하는게 없는 만능의 엄마친구아들을 뜻하죠. 적어도 프로그래밍 세계에선 은총알이나 엄친아 같은 프로그래밍언어는 없는거 같습니다. 아무리 C#이 발전했다 한들, 하자면 할 수 있지만 어색한 부분이 있다는 거죠. 그럼 오늘은 거기에 대해서 좀 이야기 해보겠습니다.


- 이거슨 F# 코드!

아래 코드는 Expert F#에 나오는 코드입니다.

open System.Collections.Generic

let devideIntoEquivalenceClasses keyf seq =
    let dict = new Dictionary<'key, ResizeArray<'a>>()
    
    seq |> Seq.iter(fun v ->
        let key = keyf v
        let ok, prev = dict.TryGetValue(key)
        if ok then prev.Add(v)
        else 
            let prev = new ResizeArray<'a>()
            dict.[key] <- prev
            prev.Add(v))
            
    dict |> Seq.map(fun group -> group.Key, Seq.readonly group.Value)

즉, 어떤 데이터의 집합과 그 데이터에 대해 수행할 함수를 받아서 각각의 데이터에 대해 그 함수를 수행합니다. 그리고 같은 결과 끼리 집합을 만들어서, 결과값과 결과값이 같은 데이터들의 집합을 Dictionary로 만들어서 리턴해주는 프로그램이죠. 즉, 함수형언어의 장점이 잘 드러나는 데이터처리부분의 예제입니다. 실행결과는 아래와 같습니다. 

> devideIntoEquivalenceClasses (fun x -> x % 3) [1..10];;
val it : seq<int * seq<int>>
= seq [(1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8]); (0, seq [3; 6; 9])]

숫자를 3으로 나눈나머지를 구하는 함수와, 1부터 10까지의 숫자를 넘겨주면, 이렇게 나머지값이 같은 숫자별로 그룹을 지어서 리턴해줍니다. 여기서 Dictionary는 닷넷의 클래스를 그대로 사용한 거구요, ResizeArray는 닷넷에서의 System.Collections.Generic.List<T>의 줄임말입입니다. 이름그대로 mutable한, 사이즈를 조절가능한 Array라는 거죠. 

코드를 보면, 전체데이터를 포함할 dict라는 Dictionary를 선언하구요, 입력으로 들어온 seq의 각요소에 대해서 사용자가 넘겨준 함수(keyf)를 수행합니다. 그리고 그 결과값이 이미 존재하는지 확인해서 존재한다면, 그 결과값을 key로 하는 ResizeArray에 숫자값을 추가하고 존재하지 않는다면, 새로운 ResizeArray를 만들어서 숫자를 추가하고, 그 ResizeArray를 dict에 추가해주는 방식입니다.

그리곤 마지막으로 key에 해당하는 ResizeArray를 읽기전용인 시퀀스로 만들어서 리턴해주고 있습니다. 이 예제는 어떤 함수에서 내부적으로는 side-effect를 가진 자료구조를 쓰더라도 그 side-effect를 오직 내부에서만 나타나게 격리한다면, 그 함수는 pure하고 functional한 함수라는 이야기를 하면서 나온 예제입니다. 그래서 마지막에 읽기전용 시퀀스로 리턴을 해주고 있는거지요. 


- 이거슨 C#코드!

이 코드를 C# 3.0버전으로 그대로 옮겨 보겠습니다. 

class Program
    {
        public Dictionary<T2, List<T1>> DivideIntoEquivalenceClasses<T1, T2>>(Func<T1,T2> func, List<T1> list)
        {
            Dictionary<T2, List<T1>> dict = new Dictionary<T2, List<T1>>();

            list.ForEach(l => {
                T2 key = func(l);
                if (dict.ContainsKey(key))
                {
                    dict[key].Add(l);
                }
                else
                {
                    List<T1> prev = new List<T1>();
                    dict[key] = prev;
                    prev.Add(l);
                }
            });

            return dict;
        }

        static void Main(string[] args)
        {
            Program program = new Program();

            var dict = program.DivideIntoEquivalenceClasses((x => x % 3), new List<INT> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

            var resultSet = dict.Select(item => new { item.Key, item.Value });

            foreach (var result in resultSet)
            {                
                Console.Write("{0},", result.Key);
                result.Value.ForEach(item => Console.Write(" {0} ", item));
                Console.WriteLine();
            }
        }
    }

실행결과는 아래과 같구요.



역시 func<>를 이용한 higher-order와 LINQ덕분에 코드의 길이자체가 별로 차이가 없고, 오히려 C#의 문법에 익숙해서 그런지 더 깔끔해 보이는 부분도 있네요. 다만, 눈에 상당히 거슬리는게 있다면, T1,T2를 비롯한 파라미터타입과 리턴타입등을 명시한 부분이 상당히 거슬리는군요. 사실 짜면서도 아직 익숙하지 않아서 일까 좀 헷갈렸습니다. F#에서는 Type inference가 제대로 적용되어서 파라미터에도 타입을 명시할 필요가 없죠. 물론 C#에서도 변수수준에서는 var타입을 이용해서 Type inference를 지원하지만, 파라미터와 리턴타입에 대해서는 지원하지 않기 때문에 쫌 복잡해질 수 있습니다. 함수형 프로그래밍을 C#에서 하느라 복잡해지는 모냥은 여기에서도 확인하실 수 있습니다. @_@.

 
아래구절은 Expert F#에서 인용한 구절인데요, 제가 설명하려는 바를 아주 잘 요약해주시고 있습니다.

 A key feature of F# is the automatic generalization of code. The combination of automatic
generalization and type inference makes many programs simpler, more succinct, and more

general. It also greatly enhances code reuse. Languages without automatic generalization force programmers to compute and explicitly write down the most general type of their functions, and often this is so tedious that programmers do not take the time to abstract common patterns of data manipulation and control.

F#의 핵심기능중의 하나가 바로 코드를 자동으로 일반화시켜주는 것이다. 자동일반화와 타입유추를 조합하게 되면 많은 프로그램을 간단하고, 좀더 명확하게 그리고 좀 더 일반화시켜서 작성할 수 있다. 당연히 코드 재사용도 아주 편리해 진다. 자동일반화를 지원하지 않는 언어는 프로그래머가 명시적으로 일반적인 타입을 계산해서 명시해야 만 한다. 그리고 이런 것들은 데이터처리와 그 처리의 흐름을 공통적인 부분을 묶어서 추상화하는 작업을 매우 손이 많이가고 짜증나는 작업으로 만든다.



- 그래서~?

즉, LINQ를 통해 C#에서의 데이터처리와 흐름의 추상화가 가능해졌으며, 그 덕에 C#으로도 부분적으로 함수형언어와 버금가는 생산성을 내는일이 가능해졌습니다. 하지만, 명령형 언어의 한계점이 이런부분일까요? 일반화를 하기 위해서 무척이나 까다롭게 인자들의 타입을 잘 명시해줘야 하는거죠. 물론, 저렇게 하는게 옳은지에 대해서는 잘 모르겠습니다. 개인적으로는 저런부분을 굳이 C#을 이용해서 구현하려고 애쓰기 보다는 F#을 이용해서 조합하는게 더 옳지 않나 싶습니다. 사실 F#을 닷넷에 편입시키려는 의도도 그런부분을 가장 기대하는게 아닌가 싶기도 하구요. 


- 참고자료

1. Expert F#, Don Syme, Adam Granicz, Antonio Cisternino, APRESS
2. http://weblogs.asp.net/podwysocki/archive/2009/04/26/functional-c-forward-functional-composition.aspx

 

Welcome to Dynamic C#(1) - 첫만남.

C# 2009. 5. 4. 14:37 Posted by 알 수 없는 사용자

-너 F#쓰던 넘이자나, Dynamic C#은 뭐냐.

안녕하세요. Welcome to F#이라는 앞뒤도 안맞고 내용도 부실하며, 불친절한 포스트를 남발하고 있는 강보람(워너비)입니다. 원래 하던거에 약간 시들해지면, 새로운 자극을 찾는다고 하던가요. F#의 포스트를 쓰는게 점점 벽에 부딛히니 C#과 자극적인 외도를..... 생각하는건 아닙니다. 하지만, 의문이 생기니 그걸 찾아보고자 하는 호기심이 생기고, 그 호기심을 오래잠재워두면 없어질거 같아서 일단 시리즈를 시작해보자! 해서 일단 무작정 Welcome to Dynamic C#이라는 시리즈를 시작해볼까 합니다. 기존에 동적언어에 대한 경험이 일천하다보니 이 시리즈의 내용역시 상당히 불친절할걸로 예상되지만, 관심있으신 분들께선 따쓰한 피드백을 주시기 바랍니다. 이제 날씨가 더워지는데 따쓰한 피드백을 주면 제가 열사병으로 죽지는 않을까 하는 염려는 고이접어 간직하시고 따쓰한 피드백을....-_-


-Paul Graham아저씨와 실용주의 아저씨들?

Paul Graham을 아십니까? "Hackers and Painters"의 저자이며, 논쟁을 불러일으킬만한 말을 참 많이도 하는 Lisp빠돌이죠. 오랜만에 Hackers and Painter를 읽다가 아래와 같은 구절을 읽고는 '이 책에 이런구절이 있었나~?' 하면서 C# 4.0의 dynamic과 DLR이 떠올랐습니다. 

A programming language is for thinking of programs, not for expressing programs you've already thought of. It should be a pencil, not a pen. Static typing would be a fine idea if people actually did write programs the way they taught me to in college. But that's not how any of the hackers I know write programs. We need a language that lets us scribble and smudge and smear, not a language where you have to sit with a teacup of types balanced on your knee and make polite conversation with a strict old aunt of a complier. 

프로그래밍언어는 프로그램에 대해서 생각해나가기 위한 것이지, 이미 머리속에 짜여져있는 프로그램을 표현하기 위한 것이 아닙니다. 프로그래밍언어는 펜이 아니라 연필이어야 합니다. 정적타입은 제가 학교에서 배우던 것 처럼만 프로그램을 짠다면 괜찮은 아이이디어 일지도 모르겠습니다. 하지만 제가 아는 해커들중에 그렇게 짜는 사람은 한명도 없더군요. 우리는 명확하지 않은 아이디어를 흐릿한 형태 그대로 빠르게 묘사할 수 있게 해주는 언어가 필요합니다. 무릎에 타입이라는 찻잔을 떨어지지 않게 올려놓고, 나이많고 엄격하신 이모님이랑 공손하게 대화하려고 애쓰는 것 처럼 컴파일러와 대화할 필요가 없다는 거죠.


그리고는 예전에 사두었던 "Programming Ruby"를 꺼내서 읽어봤습니다. "실용주의 프로그래머"를 읽으면서 실용주의 학파로 유명한 데이비드 토머스와 앤디 헌트가  펄에서 루비로 관심사를 옮겼다는 사실은 알고 있었지만, 이 책을 읽으면서 이들의 동적언어에 대한 사랑이 확실하게 드러나더군요.

반면에 루비를 잠깐이라도 사용해본다면, 동적 타입을 갖는 변수가 많은 점에서 실질적으로 생산성을 향상시킴을 알게 될 것이다. 오랜 기간 실행되는 커다란 루비 프로그램이 중요한 작업을 수행하면서도, 타입과 관련된 오류는 하나도 던지지 않고 잘 돌아간다. 왜 일까? ..... 결론적으로 말해 '타입 안전성'에서 말하는 '안전성'이란 대개 허상에 불과하며, 루비 같은 동적 언어로 개발하는 것은 안전하면서도 생산적이다.

이런 호기심이 생기자, F#때문에 미뤄오던 C#4.0의 dynamic에 대한 탐구를 더 이상 미룰 수 없다는 생각이 들었습니다. 그래서 가끔 생각날때 마다 dynamic에 대한 생각을 정리해서 올리려고 지금 포석을 깔고자 하는 것이죠. 대뜸 F#에 대해서 쓰다가 C#으로 옮겨가면, 읽으시는 분들도 혼란을 느끼시지 않을까 해서 말이죠. 물론 그런분덜 한분도 없을거 압니다-_-. 


-반갑다! dynamic! 

일단, dynamic에 대해서 조금 알아보도록 하겠습니다. dynamic은 말 그대로 동적이라는 거구요, 타입체크를 컴파일 타임이 아니라 수행순간에 즉, 런타임에서 하겠다는 말이 됩니다. 여기서 Duck typing이라는 개념이 들어가게 되는데요, Duck typing은 객체의 타입에 따라서 가능여부를 결정하는 게 아니라, 그저 요건을 갖추고 있다면 모두다 가능하다고 보는 거죠. 즉, 비유를 하나 하자면 조선시대의 어떤 모임을 생각해 보겠습니다.

이 모임에서 양반집의 지체높은 어르신들과 그 어르신들의 자제들만 회원으로 받아준다면 이 모임은 정적타입검사(Static type check)를 하고 있는셈입니다. 특정 계급(Type)만 들여보내주기 때문이죠. 타입이 틀리면 아예들어갈 수가 없습니다. 하지만, 어떤 모임에서는 그림에 관심이 있는 사람이라면, 양반이나 상놈 가리지 않고 모두다 받아들여줬습니다. 이 모임은 바로 Duck typing을 충실히 따르고 있는셈입니다. 계급(타입)에 상관없이 그저 공통점(그림을 사랑하는 뜨거운 가슴!)만 있으면 들여보내주기 때문이죠. Duck typing은 이처럼 타입으로 가르지 않고, 요건을 갖췄다면 모두 묻지도 따지지도 않고 받아들여주는 걸 이야기 합니다.(Duck이 들어가 있는 이유는 애초에 이 개념을 설명하신 분께서 오리처럼 걷고 꽥거리면 전부다 오리로 봐주자고 말씀하셨기 때문이죠. 제가 안그랬습니다-_-. 오히려 제가 만들었다면, '동호회 타이핑' 같은용어를 썼을거 같은데... 제가 안만든게 다행이군요.) 

그럼 첫 예제를 한번 볼까요? 

static void Main(string[] args)
{
            dynamic num = 4;

            Console.WriteLine(num);
 

            Type type = num.GetType();
            MethodInfo method = type.GetMethod("ToString", new Type[] {});

            if (method != null)
            {
                Console.WriteLine(method.ToString());
            }
} 

위 예제는 dynamic타입의 num에 숫자인 4를 입력하고, 출력을 합니다. 그리고 WriteLine에 의해서 불려지는 ToString메서드의 유무를 검사하기 위해서, 타입에서 ToString메서드를 찾아서 출력하는 프로그램입니다. 결과는 아래와 같습니다. 



WriteLine에선 출력할 객체의 ToString을 호출하죠. 그래서 num의 값이 출력되는 것을 보면 런타임에 num이 ToString을 가지고 있는지 확인해서 있으니까 출력을 했다고 볼 수 있습니다. 그리고 확인을 위해서 dynamic타입인 num의 타입에서 ToString메서드를 찾아서 해당 메서드를 출력해봅니다. 결과를 보면 ToString이 있는 것을 볼 수 있습니다. 그리고 WriteLine의 오버로딩중에서 dynamic타입을 인자로 받아들이는 오버로딩이 없는걸로 봐서는, 런타임에 해당 dynamic객체가 ToString을 가지고 있는지 봐서 있으면 출력하고, 없으면 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException을 발생시키는 것을 유추할 수 있습니다.


-양반과 상놈의 이야기 

그럼 위에서 이야기 했던, 양반과 상놈의 이야기를 한번 구현해볼까요? 

class Yangban
    {
        public string Name {get; set;}

        public void YangbanSound()
        {
            Console.WriteLine("Yo, it's the yangban sound, baby :) ");
        }
    }

    class YangbanChild : Yangban
    {
        public void ILikeDrawing()
        {
            Console.WriteLine("I like Drawing");
        }
    }

    class Sangnom
    {
        public string Name { get; set; }

        public void SangnomSound()
        {
            Console.WriteLine("Yo, it's the sangnom sound, baby ;) ");
        }

        public void ILikeDrawing()
        {
            Console.WriteLine("I like Drawing");
        }
    }

    class Program
    {
        public void EnteringYangbanClub(Yangban yangban)
        {
            Console.WriteLine("Welcome yangban {0}!", yangban.Name);
        }

        public void EnteringDrawingClub(dynamic person)
        {
            try
            {
                person.ILikeDrawing();
                Console.WriteLine("Welcome {0}! who like drawing",person.Name);
            }
            catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException you_do_not_like_drawing)
            {
                Console.WriteLine("{0}. You can't come in. I'm sorry about that :)", person.Name);
            }
        }

        static void Main(string[] args)
        {
            Yangban yangban1 = new Yangban { Name = "chulsoo" };
            YangbanChild yangbanChild1 = new YangbanChild { Name = "chulsooAdeul" };
            Sangnom sangnom1 = new Sangnom { Name = "boram" };

            Program program = new Program();
            program.EnteringDrawingClub(yangban1);
            program.EnteringDrawingClub(yangbanChild1);
            program.EnteringDrawingClub(sangnom1);
        }
    }

위 코드를 보시면, 양반과 양반자식, 상놈이 있죠? 모두 이름을 가지고 있구요, 양반은 간지나는 양반사운드를 구사하며, 상놈은 상놈사운드 그리고 양반자식과 상놈은 자기가 그림그리는걸 좋아한다고 합니다. 그리고 두개의 클럽이 있습니다. 하나는 양반만 들어갈 수 있는 클럽이구요, 하나는 그림을 좋아하는 사람이 들어갈 수 있는 클럽입니다. 자 그럼, 양반과 양반자식인 철수와 철수아들, 상놈인 보람을 데리고 이야기를 해보겠습니다. 양반클럽에 철수와 철수아들, 보람 이렇게 셋이 들어가려고 합니다. 그런데, 양반클럽은 양반이거나 양반의 자제가 아니면 못들가게 엄격하게 막아놨습니다. 그래서 일까요? 아래 그림을 보면, 들어가고 싶다는 의사표시조차도 허용되지 않는 슬픈 모습입니다. 

뭐, 계급으로 딱 막혀있기 때문에 들어가는거 자체가 불가능하니까요. 이렇게 타입으로 조건을 걸게되면, 해당타입이거나 해당타입을 상속한 타입이 아니면 안됩니다. 그러면, 그림애호가 클럽에 들어가보도록 하겠습니다. 그림애호가클럽은 일단 다 들여보내주는 군요. 하지만, 들어가게되면 그림을 좋아하는지 크게 외쳐보라고 시킵니다. 근데, 철수는 그림을 좋아하지 않는군요. 그래서 철수는 쫓겨나고 철수아들과 보람은 환영받습니다. 실행결과는 아래와 같죠.


그렇습니다. 계급으로 나누것이 아니라 무엇을 할 수 있는지에 따라 니편 내편을 나누니깐 철수는 못들어가고 보람은 들어가게 되는 것이죠.


-근데 dynamic이거 어따 쓰면 조으까? 

도대체 이걸로 무엇을 할 수 있다는 걸까요? 왜 Paul Graham아저씨는 그토록 다이나믹을 부르짖었으며, 실용주의 아저씨들은 또 왜그랬을까요? 불행히도 저는 그동안 정적인 명령형 언어만 다뤄봤기 때문에 잘 모르겠습니다. 뭐 좀 알아보려고 하는데, 그 과정에서 느끼는 점들을 이곳을 통해 나눠보려고 하는거구요. 그럼 F#뿐만 아니라 C#을 통해서 최대한 자주 찾아뵙겠습니다.


-참고자료

1. Hackers and Painters, Paul Graham, O'Reilly
2. Programming Ruby, 데이비드 토머스, 앤디 헌트, 차드파울러, 인사이트
3. http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=csharpfuture&DownloadId=3550

[Better Code]Visualize Code Relationships

Agile Development 2009. 5. 2. 18:40 Posted by kkongchi

image

위 그림처럼 이번 Visual Studio Team System 2010에서는 Analyze(분석) 메뉴에 새로운 기능이 하나 더 추가되었습니다. 바로 Visualize Code Relationships 메뉴입니다. (아직 한글로는 어떻게 번역될 지 잘 모르겠네요)

이 기능은 제목 그대로 코드의 관계를 시각화해서 보여 줍니다. UML 다이어그램과도 조금 다르고, 모델링 용의 DSL 다이어그램과도 조금 다르긴 하지만, 꽤 괜찮은 그림을 보여줍니다.

그림을 한 번 보기 위해서, 아래와 같은 아주 간단한 Visual Studio 솔루션을 한 번 구성해봤습니다.

image

구조는 간단합니다. WebApplication1이 WebService1을 Web Reference를 해서 호출하고, 다시 WebService1은 ClassLibaray1을 내부적으로 Reference해서 호출하는, 아주 흔한 형태의 Application 구조입니다. 그리고 ClassLibrary1 내부에서 Class2는 Class1을 사용합니다.

이 구조가 어떻게 시각화 되는지 한 번 볼까요?

1. Visualize Call Dependency – By Assembly

image

오른쪽 옆의 버튼을 누르면, 내부로 펼쳐지면서, 내부에 들어있는 클래스도 보입니다.

image 

2. Visualize Call Dependency – By Namespace

image

3. Visualize Call Dependency – By Class

image

프로젝트가 성숙하고 발전되면, 코드도 따라서 많아지면서 구조도 복잡해지기 마련입니다. 복잡도가 높아지면 높아질 수록 유용한 툴이 되지 않을까 싶습니다.

하지만, 지금 그림을 보시면 아시겠지만, WebApplication1이 Web Service1를 Web 참조를 하고 있습니다만 그림에는 그 참조 관계는 표시가 제대로 되질 않네요. 결국 직접적인 참조 외에는 다이어그램에서 보기가 힘든 것 같습니다. 쉽지 않겠지만, 그런 부분들도 표시할 수 있었더라면 정말 환상적이었을 텐데 하는 생각이 듭니다.

 

지난 번 글에서 Visual Studio Team System 2010의 향상된 Unit Test 기능에 대해서 살펴 본 바가 있었습니다. 오늘 소개드릴 PEX는 Microsoft Research 그룹에서 개발한 Automated Whitebox Testing Framework 입니다. 꽤나 긴 정의입니다만, 간단히 말하자면 자동으로 코드를 분석해서 WhiteBox Unit Test를 만들어주는 Visual Studio Extension입니다.

Blackbox Test – Blackbox Test는 우리가 코드 내부에 대한 지식이 없다는 것을 전제로 합니다. Blackbox Test에서는 코드의 노출된 API를 소비하는 Consumer의 입장에서 Function을 테스트하게 됩니다. 비교적 초기에 작성되는 Unit Test들은 이 Blackbox Test가 됩니다. 아직 Code가 성숙되지 않은 상태에서 API의 Requirements, Specification 등만을 가지고 테스트를 작성하게 되기 때문입니다. 하지만 코드 개발이 점점 진행됨에 따라서 Unit Test는 Whitebox Test로 이행되게 됩니다.

Whitebox Test – Whitebox Test는 코드 내부를 알고 있다는 것을 전제로 하는 테스트입니다. 우리는 코드를 알기 때문에 모든 가능한 성공/실패 시나리오를 모두 알 수가 있고, 특정 데이터나 입력 조건이 어떤 Flow를 따르는지에 대해서 충분하게 알 수 있습니다. 이런 가능한 모든 시나리오에 대해서 Unit Test를 작성하고 수행하게 되면 그것을 Whitebox Test라고 말할 수가 있습니다.

* 이는 Blackbox Test, Whitebox Test에 대한 일반적인 정의가 아니라, Unit Test관점에서 바라본 정의입니다. 일반적인 정의에 대해서는 Wikipedia의
Whitebox Testing, Blackbox Testing 항목들을 참고하시기 바랍니다.

Unit Test를 수행할 때에 대개 Code Coverage Test를 같이 수행하는 이유가 바로 우리가 작성한 Unit Test가 어느 정도 수준의 Whitebox Testing에 도달했는지를 알 수가 있기 때문입니다. 당연히 우리가 작성한 모든 코드에 대해서 완벽한 Whitebox Testing을 Unit Test를 통해서 수행했다면 Code Coverage Test의 결과는 100%가 되어야 합니다. 하지만, 실제로 Unit Test건 Manual Test Case건 Code Coverage Test결과가 100%에 도달하기는 참으로 힘듭니다. 일반적으로 80%정도를 목표로 하지만, 그 이하가 되는 경우가 대부분입니다. 그것은 복잡성의 문제이기도 하고, 비용 대비 효과의 문제이기도 합니다. 코드의 모든 경로를 통과하는 Unit Test를 작성하려면 엄청난 시간이 소요될 테니까요.

이 점이 PEX라는 제품이 나오게 된 배경이라고 할 수 있습니다. PEX는 Visual Studio의 코드를 분석해서, Input과 output 조합을 찾아서 자동으로 테스트 코드를 만들어 줍니다. 자동으로 생성된 테스트 코드이지만, 높은 Coverage를 보여 줍니다. PEX를 사용하면, Unit Test 작성에 들이는 수고를 상당히 줄일 수 있을 것 같습니다.

 

PEX 홈페이지는 http://research.microsoft.com/en-us/projects/pex/default.aspx 이며, 현재 Visual Studio Team System 2008과 2010에서 사용할 수 있다고 되어 있습니다. 즉, 현재 VSTS 2008을 쓰고 계시는 개발자 분이라면 다운로드 받아서 써 보실 수 있다는 의미입니다. 현재 정식 버전은 아니고 Pre-release 버전입니다. 그리고 Visual Studio 2008 Professional 버전을 위한 비 상업용 Academic 버전도 다운로드 받을 수 있습니다. 다운로드 링크는 http://research.microsoft.com/en-us/projects/pex/downloads.aspx 입니다.

이번 글은 개요이니까, PEX Tutorial에 나오는 간단한 샘플만 잠시 보도록 하겠습니다.

   1:  [PexMethod]
   2:  public void ParameterizedTest(int i)
   3:  {
   4:       if (i == 123)
   5:           throw new ArgumentException("i");
   6:  }

Integer 타입의 매개 변수를 받는 간단한 메소드입니다. 매개 변수가 123일 때에는 ArgumentException을 일으키는 딱 두 줄의 구현만 있을 뿐입니다. PexMethod Attribute는 이 메소드가 PEX Test method라는 것을 의미합니다. 이 메소드에 대고 마우스 오른쪽 클릭을 하게 되면 컨텍스트 메뉴에 다음과 같이 PEX 관련 메뉴들이 보이게 됩니다.

여기서 Run Pex Explorations를 선택하게 되면, PEX가 자동으로 코드를 분석해서 가능한 모든 매개 변수를 대입해 본 다음 그 결과를 바탕으로 아래처럼 결과를 보여주게 됩니다.

이 부분 – Run Pex Exploration 실행 - 에서 저는 예상치 못했던 에러를 만났습니다.

[critical] unexpected failure during exploration
System.IO.FileLoadException: Could not load file or assembly 'Microsoft.Z3, Version=2.0.30325.1, Culture=neutral, PublicKeyToken=9c8d792caae602a2' or one of its dependencies.


위와 같은 에러였는데, 이 에러는 Visual C++을 설치하지 않았을 때에 발생하는 것으로 보입니다. 아직 PEX 설치 파일이 어떤 조건에서도 완벽하게 모든 필요한 파일들을 설치하지 못하는 것 같습니다. 이 에러는 Visual C++ 2008 SP1 Redistributable Package를 다운로드해서 설치하는 것으로 해결할 수 있습니다. 이 정보는 http://social.msdn.microsoft.com/Forums/en-US/pex/thread/5862d522-0c2e-481c-b537-864e7427a7e5 에서 얻었습니다. 혹시 Visual C++ 가 설치되지 않은 분들은 참고하시기 바랍니다.

예상대로 123이라는 매개변수가 입력되었을 때에 ArgumentException이 발생한 것을 볼 수가 있습니다. 그리고 여기서 또 다시 마우스 오른쪽 컨텍스트 메뉴를 통해서 Go To를 선택하게 되면 실제 자동으로 생성된 테스트 코드를 아래 그림처럼 볼 수가 있습니다.

   1:  [TestMethod]
   2:  [PexGeneratedBy(typeof(HelloWorldTest))]
   3:  public void ParameterizedTest01()
   4:  {
   5:      this.ParameterizedTest(0);
   6:  }
   7:   
   8:  [TestMethod]
   9:  [PexGeneratedBy(typeof(HelloWorldTest))]
  10:  [PexRaisedException(typeof(ArgumentException))]
  11:  public void ParameterizedTest02()
  12:  {
  13:       this.ParameterizedTest(123);
  14:  }

간단한 샘플이긴 하지만, PEX의 강력한 자동 테스트 코드 생성 기능을 볼 수 있으셨을 거라고 생각합니다. 다음 포스팅에서는 PEX에 대해서 더 깊이 들어가 보겠습니다. 아 물론, Code Analysis에 대한 글들도 계속 올릴 예정입니다. 읽어주셔서 감사합니다.