Programming/openCL & CUDA2011. 2. 5. 23:42
CUDA Driver API나 Runtime API는 원칙적으로 하나의 GPU를 사용하여
하나의 GPU내의 멀티쓰레드를 사용하도록 설계되어 있다. 이러한 제어의 관리를 컨텍스트 라고 지칭해도 될 지 모르겠지만
이러한 기본 컨텍스트는 1번 GPU를 사용하도록 되어있고,
Runtime API 쪽에서는 cudaSetDevice (int device) 라는 함수로 특정 GPU를 사용하도록 제한할 수 있다.

하지만 Driver API에는 이러한 함수가 존재하지 않으므로
직접 Handle을 이용하여 openMP 나 thread 등을 이용하여 직접 여러개의 CPU 쓰레드를 이용하여
GPU를 여러개 동시에 가동시키는 방법을 사용하는 것으로 보여진다.

8.2  Multi-GPU Programming 

 In order to issue work to a GPU, a context is established between a CPU thread and the GPU.  Only one context can be active on GPU at a time.  Similarly, a CPU thread can have one active context at a time.  A context is established during the program’s first call to a function that changes state (such as cudaMalloc(), etc.), so one can force the creation of a context by calling cudaFree(0).  Note that a context is created on GPU 0 by default, unless another GPU is selected explicitly prior to context creation with a cudaSetDevice() call.  Context is destroyed either with a cudaThreadExit() call, or when the controlling CPU thread exits.

 CUDA driver API allows a single CPU thread to manage multiple contexts (and therefore multiple GPUs) by pushing/popping contexts.  In the remainder of the document we will focus on CUDA runtime API, which currently allows strictly one context per CPU thread. 

 In order to issue work to p GPUs concurrently, a program needs p CPU threads, each with its own context. Threads can be lightweight (pthreads, OpenMP, etc.) or heavyweight (MPI).  Note that any CPU multi-threading or message-passing API or library can be used, as CPU thread management is completely orthogonal to CUDA.  
For example, one can add GPU processing to an existing MPI application by porting the compute-intensive portions of the code without changing the communication structure. 

 Even though a GPU can execute calls from one context at a time, it can belong to multiple contexts.  For example, it is possible for several CPU threads to establish contexts with the same GPU.  This allows developing multi-GPU applications on a single GPU.  GPU driver manages GPU switching between the contexts, as well as 
partitioning memory among the contexts (GPU memory allocated in one context cannot be accessed from another context). 

[출처 : CUDA_C_Best_Practices_Guide.pdf / Chapter 8]

CUDA Toolkit SDK의 예제는 threadMigration를 참조하면 될 듯
/******************************************************************************
*
*   Module: threadMigration.cpp
*
*   Description:
*     Simple sample demonstrating multi-GPU/multithread functionality using 
*     the CUDA Context Management API.  This API allows the a CUDA context to be
*     associated with a CPU process.  CUDA Contexts have a one-to-one correspondence 
*     with host threads.  A host thread may have only one device context current 
*     at a time.
*
*    Refer to the CUDA programming guide 4.5.3.3 on Context Management
*
******************************************************************************/


MonteCarloMultiGPU 예제에도 cutil 을 이용한 예제가 존재하는 것으로 보인다.
       //Start CPU thread for each GPU
        for(gpuIndex = 0; gpuIndex < GPU_N; gpuIndex++)
            threadID[gpuIndex] = cutStartThread((CUT_THREADROUTINE)solverThread, &optionSolver[gpuIndex]);

    printf("main(): waiting for GPU results...\n");
        cutWaitForThreads(threadID, GPU_N);

cutStartThread는 multithreading.h 에 포함되어 있는 녀석이다.
#if _WIN32
    //Create thread
    CUTThread cutStartThread(CUT_THREADROUTINE func, void *data){
        return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, data, 0, NULL);
    }
#endif
그리고 이런식으로 해당 OS의 Thread로 연결되어 있다.

'Programming > openCL & CUDA' 카테고리의 다른 글

CUDA processor roadmap / CUDA SDK 4.0  (1) 2011.07.03
CUDA 4.0 RC  (4) 2011.03.02
CUDA driver API / runtime API  (0) 2011.01.26
SLI에 대한 CUDA의 제한(과거에는 그랬다더라~)  (0) 2011.01.26
cuBLAS / BLAS Level 1,2,3  (0) 2011.01.24
Posted by 구차니
Programming/openCL & CUDA2011. 1. 26. 22:59
SDK 예제를 보다보니 drv 라는 접미가 붙은 샘플이 있어서
내용을 보다보니, Driver API를 이용한 것이라고 기술되어 있다.

아무튼 CUDA는 Runtime API와 Driver API로 구분이 되는데
접두가 cuda(RT)와 cu(driver)로 나뉜다.

[링크 : http://developer.download.nvidia.com/.../group__CUMEM.html]                  Driver - Memory 




음.. 이거 이미지 하나로 설명 끝?
Runtime은 결국 Driver API를 감싼것이고, 결국에는 Driver API보다는 성능의 저하는 감수할 수 밖에 없을듯.

'Programming > openCL & CUDA' 카테고리의 다른 글

CUDA 4.0 RC  (4) 2011.03.02
CUDA - Multi GPU 프로그래밍  (1) 2011.02.05
SLI에 대한 CUDA의 제한(과거에는 그랬다더라~)  (0) 2011.01.26
cuBLAS / BLAS Level 1,2,3  (0) 2011.01.24
CUDA 관련 해외글  (0) 2011.01.22
Posted by 구차니
Programming/openCL & CUDA2011. 1. 26. 20:21
과거에는 CUDA 드라이버가 SLI 사용시에는 첫 GPU만 보이도록 제한되어 있었는데 이제는 그러한 제한이 풀렸다.
라는 이야기 -_-
일단 공식 내용은 발견못했으니 카더라 통신으로 일단 만족.

 In the past, the CUDA driver had a limitation and would only show you the first GPU if you had SLI enabled. That restriction has been removed, and now you will see both devices even if SLI is turned on. SLI is only beneficial to 3D rendering. 

[링크 : http://forums.nvidia.com/index.php?showtopic=186498]

'Programming > openCL & CUDA' 카테고리의 다른 글

CUDA - Multi GPU 프로그래밍  (1) 2011.02.05
CUDA driver API / runtime API  (0) 2011.01.26
cuBLAS / BLAS Level 1,2,3  (0) 2011.01.24
CUDA 관련 해외글  (0) 2011.01.22
CUDA에서 grid 와 thread 의 갯수에 대한 짧은생각  (2) 2011.01.18
Posted by 구차니
Programming/openCL & CUDA2011. 1. 22. 00:11
CUDA를 보면서 헷갈리는 것은
nvidia의 문서라고 해도 버전에 따라서 용어가 혼용이 되어있기 때문이다.

현재로서 가장 혼동을 일으키는 용어는 바로 grid / block / thread 이다.
DeiveQurey 프로그램에서 주는 값들 중, 위의 녀석들의 Dimension(차수)이 바로 범인인데..
여러가지 프리젠테이션들과 문서들을 조합할수록 불일치가 발생을 해서 머리를 아프게 한다.

아무튼 Grid는 Block들로 구성되므로, Grid의 최대 차수는
Block의 차수를 의미하고, Block은 2차원 내지는 1차원으로만 구성이 된다.
그리고 Block은 65535x65535x1 개 까지 구성이 가능하다.

개별 Block은 thread로 구성이 되며, 블럭은 개별 MultiProcessor에 제한된다.
8800GT의 경우 1개의 MP에 512개의 Thread 들이 존재하며,
그런 이유로 3차원으로 구성을 한다고 해도 x*y*z의 곱은 512를 넘을수 없다.
(물론 상위 버전은 768까지 제한이 조금 커진다)

다시 정리하자면
Maximum number of threads per block:           512
Maximum sizes of each dimension of a block:    512 x 512 x 64
위의 값은, 블럭의 최대 차수는 3차원으로 512*512*64 이지만
세 차수의 곱이 512를 넘을수는 없다라는 의미이다.

Maximum sizes of each dimension of a grid:     65535 x 65535 x 1
block은 2차원으로 65535x65535를 넘을 수 없다는 의미이다.

Posted by 구차니
Programming/openCL & CUDA2011. 1. 18. 22:29
DeviceQuery 프로그램을 실행하면 다음과 같은 내용이 나온다.
  Maximum sizes of each dimension of a block:    512 x 512 x 64
  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1

블럭의 차원은 512x512x64 3차원으로 구성이 가능하고
그리드의 차원은 65535x65535x1 2차원으로 구성이 가능하다.

여전히 그리드와 블럭 쓰레드, 이러한 연관관계가 확실히 정립된게 아니라 헷갈리지만
kernel<<<block,thread>>>(agrs) 에서
그리드의 차원은 block 이고 
블럭의 차원은 thread 인거 같은데(아무래도 차수가 제한된게 같으니까)

실제로 존재하는 쓰레드의 갯수라던가, 멀티프로세서의 갯수를 감안하면 절대 불가능한 수치이다.
8800GT의 경우
14개의 멀티프로세서와 개당 8개씩의 코어(쓰레드 블럭)이 존재함으로
총 112개의 쓰레드 블럭이 존재하기 때문에
물리적으로는 블럭의 차원은 14x8x1 정도가 한계라고 볼 수 있다.


하지만, 논리적으로는 한번의 처리단위가 14x8x1 이므로
X/Y/Z 차원으로 n번씩 반복하게 되면 돌릴수 있게 되고 이럴경우
X차원으로는 37번
Y차원으로 64번
Z차원으로 64번 이런식으로 더 반복하게 하면 무리없이 가능하다.


내부적으로 BlockIdx 라는 변수만 thread block 에서 값만 바꾸어서 넘겨주면 되니까 말이다.




결론 : 위에서 명시되는 최대차원은 논리적으로 제한을 둔 값으로 생각된다.

'Programming > openCL & CUDA' 카테고리의 다른 글

cuBLAS / BLAS Level 1,2,3  (0) 2011.01.24
CUDA 관련 해외글  (0) 2011.01.22
CUDA 3.1과 3.2의 devicequery 결과 차이점  (0) 2011.01.18
vectorAdd 를 이용한 CUDA 연습  (0) 2011.01.18
CUDA 메모리별 범위(scope)  (0) 2011.01.17
Posted by 구차니
Programming/openCL & CUDA2011. 1. 18. 22:20
별건없고, 멀티프로세서와 core의 출력방식이 변경되었다.

CUDA SDK 3.1

D:\CUDA\NVIDIA GPU Computing SDK\C\bin\win32\Release\deviceQuery.exe Starting...


 CUDA Device Query (Runtime API) version (CUDART static linking)

There are 2 devices supporting CUDA

Device 0: "GeForce 8800 GT"
  CUDA Driver Version:                           3.20
  CUDA Runtime Version:                          3.10
  CUDA Capability Major revision number:         1
  CUDA Capability Minor revision number:         1
  Total amount of global memory:                 536543232 bytes
  Number of multiprocessors:                     14
  Number of cores:                               112
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       16384 bytes
  Total number of registers available per block: 8192
  Warp size:                                     32
  Maximum number of threads per block:           512
  Maximum sizes of each dimension of a block:    512 x 512 x 64
  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1
  Maximum memory pitch:                          2147483647 bytes
  Texture alignment:                             256 bytes
  Clock rate:                                    1.50 GHz
  Concurrent copy and execution:                 Yes
  Run time limit on kernels:                     Yes
  Integrated:                                    No
  Support host page-locked memory mapping:       Yes
  Compute mode:                                  Default
                             (multiple host threads can use this device simultaneously)
  Concurrent kernel execution:                   No
  Device has ECC support enabled:                No

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 3.20, CUDA Runtime Vers
ion = 3.10, NumDevs = 2, Device = GeForce 8800 GT, Device = GeForce 8800 GT


PASSED

Press <Enter> to Quit...
-----------------------------------------------------------




CUDA SDK 3.2
D:\CUDA\NVIDIA GPU Computing SDK 3.2\C\bin\win32\Release\deviceQuery.exe Starting...

 CUDA Device Query (Runtime API) version (CUDART static linking)

There are 2 devices supporting CUDA

Device 0: "GeForce 8800 GT"
  CUDA Driver Version:                           3.20
  CUDA Runtime Version:                          3.20
  CUDA Capability Major/Minor version number:    1.1
  Total amount of global memory:                 536543232 bytes
  Multiprocessors x Cores/MP = Cores:            14 (MP) x 8 (Cores/MP) = 112 (Cores)
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       16384 bytes
  Total number of registers available per block: 8192
  Warp size:                                     32
  Maximum number of threads per block:           512
  Maximum sizes of each dimension of a block:    512 x 512 x 64
  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1
  Maximum memory pitch:                          2147483647 bytes
  Texture alignment:                             256 bytes
  Clock rate:                                    1.50 GHz
  Concurrent copy and execution:                 Yes
  Run time limit on kernels:                     Yes
  Integrated:                                    No
  Support host page-locked memory mapping:       Yes
  Compute mode:                                  Default
                             (multiple host threads can use this device simultaneously)
  Concurrent kernel execution:                   No
  Device has ECC support enabled:                No
  Device is using TCC driver mode:               No

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 3.20, CUDA Runtime Vers
ion = 3.20, NumDevs = 2, Device = GeForce 8800 GT, Device = GeForce 8800 GT


PASSED

Press <Enter> to Quit...
-----------------------------------------------------------

Posted by 구차니
Programming/openCL & CUDA2011. 1. 18. 22:12
warp 크기는 32 라는데,
그 이하로도 묶어서 사용이 가능한지 테스트를 해보았다.

VectorAdd를 변형해서 int 형으로 계산하고, 변수는 총 64개의 int형 배열로 선언
그리고 커널코드는 단순하게 두개의 배열을 더해서 세번째로 던져주게 해놓았다.

단, 커널은 1 block / 5 thread로 설정했다.
// Device code
__global__ void VecAdd(const int* A, const int* B, int* C, int N)
{
int i = threadIdx.x;
C[i] = A[i] + B[i];
}

VecAdd<<<1,5>>>(d_A, d_B, d_C, N);

결과는 아래와 같이 5개만 계산이 되어 나온다.
Vector addition
[000] h_A[0] + h_B[0] = 0, h_C[0]
[001] h_A[1] + h_B[1] = 2, h_C[2]
[002] h_A[2] + h_B[2] = 4, h_C[4]
[003] h_A[3] + h_B[3] = 6, h_C[6]
[004] h_A[4] + h_B[4] = 8, h_C[8]
[005] h_A[5] + h_B[5] = 10, h_C[133]- not ok
[006] h_A[6] + h_B[6] = 12, h_C[134]- not ok
[007] h_A[7] + h_B[7] = 14, h_C[135]- not ok
[008] h_A[8] + h_B[8] = 16, h_C[136]- not ok
[009] h_A[9] + h_B[9] = 18, h_C[137]- not ok
[010] h_A[10] + h_B[10] = 20, h_C[138]- not ok
[011] h_A[11] + h_B[11] = 22, h_C[139]- not ok
[012] h_A[12] + h_B[12] = 24, h_C[140]- not ok
[013] h_A[13] + h_B[13] = 26, h_C[141]- not ok
[014] h_A[14] + h_B[14] = 28, h_C[142]- not ok
[015] h_A[15] + h_B[15] = 30, h_C[143]- not ok
[016] h_A[16] + h_B[16] = 32, h_C[144]- not ok
[017] h_A[17] + h_B[17] = 34, h_C[145]- not ok
[018] h_A[18] + h_B[18] = 36, h_C[146]- not ok
[019] h_A[19] + h_B[19] = 38, h_C[147]- not ok
[020] h_A[20] + h_B[20] = 40, h_C[148]- not ok
[021] h_A[21] + h_B[21] = 42, h_C[149]- not ok
[022] h_A[22] + h_B[22] = 44, h_C[150]- not ok
[023] h_A[23] + h_B[23] = 46, h_C[151]- not ok
[024] h_A[24] + h_B[24] = 48, h_C[152]- not ok
[025] h_A[25] + h_B[25] = 50, h_C[153]- not ok
[026] h_A[26] + h_B[26] = 52, h_C[154]- not ok
[027] h_A[27] + h_B[27] = 54, h_C[155]- not ok
[028] h_A[28] + h_B[28] = 56, h_C[156]- not ok
[029] h_A[29] + h_B[29] = 58, h_C[157]- not ok
[030] h_A[30] + h_B[30] = 60, h_C[158]- not ok
[031] h_A[31] + h_B[31] = 62, h_C[159]- not ok
[032] h_A[32] + h_B[32] = 64, h_C[160]- not ok
[033] h_A[33] + h_B[33] = 66, h_C[161]- not ok
[034] h_A[34] + h_B[34] = 68, h_C[162]- not ok
[035] h_A[35] + h_B[35] = 70, h_C[163]- not ok
[036] h_A[36] + h_B[36] = 72, h_C[164]- not ok
[037] h_A[37] + h_B[37] = 74, h_C[165]- not ok
[038] h_A[38] + h_B[38] = 76, h_C[166]- not ok
[039] h_A[39] + h_B[39] = 78, h_C[167]- not ok
[040] h_A[40] + h_B[40] = 80, h_C[168]- not ok
[041] h_A[41] + h_B[41] = 82, h_C[169]- not ok
[042] h_A[42] + h_B[42] = 84, h_C[170]- not ok
[043] h_A[43] + h_B[43] = 86, h_C[171]- not ok
[044] h_A[44] + h_B[44] = 88, h_C[172]- not ok
[045] h_A[45] + h_B[45] = 90, h_C[173]- not ok
[046] h_A[46] + h_B[46] = 92, h_C[174]- not ok
[047] h_A[47] + h_B[47] = 94, h_C[175]- not ok
[048] h_A[48] + h_B[48] = 96, h_C[176]- not ok
[049] h_A[49] + h_B[49] = 98, h_C[177]- not ok
[050] h_A[50] + h_B[50] = 100, h_C[178]- not ok
[051] h_A[51] + h_B[51] = 102, h_C[179]- not ok
[052] h_A[52] + h_B[52] = 104, h_C[180]- not ok
[053] h_A[53] + h_B[53] = 106, h_C[181]- not ok
[054] h_A[54] + h_B[54] = 108, h_C[182]- not ok
[055] h_A[55] + h_B[55] = 110, h_C[183]- not ok
[056] h_A[56] + h_B[56] = 112, h_C[184]- not ok
[057] h_A[57] + h_B[57] = 114, h_C[185]- not ok
[058] h_A[58] + h_B[58] = 116, h_C[186]- not ok
[059] h_A[59] + h_B[59] = 118, h_C[187]- not ok
[060] h_A[60] + h_B[60] = 120, h_C[188]- not ok
[061] h_A[61] + h_B[61] = 122, h_C[189]- not ok
[062] h_A[62] + h_B[62] = 124, h_C[190]- not ok
[063] h_A[63] + h_B[63] = 126, h_C[191]- not ok
PASSED


2개씩 3개 블럭을 사용해도 제대로 나온다.
__global__ void VecAdd(const int* A, const int* B, int* C, int N)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
C[i] = A[i] + B[i];
}
VecAdd<<<3,2>>>(d_A, d_B, d_C, N);

Vector addition
[000] h_A[0] + h_B[0] = 0, h_C[0]
[001] h_A[1] + h_B[1] = 2, h_C[2]
[002] h_A[2] + h_B[2] = 4, h_C[4]
[003] h_A[3] + h_B[3] = 6, h_C[6]
[004] h_A[4] + h_B[4] = 8, h_C[8]
[005] h_A[5] + h_B[5] = 10, h_C[10]
[006] h_A[6] + h_B[6] = 12, h_C[134]- not ok
[007] h_A[7] + h_B[7] = 14, h_C[135]- not ok
[008] h_A[8] + h_B[8] = 16, h_C[136]- not ok
[009] h_A[9] + h_B[9] = 18, h_C[137]- not ok
[010] h_A[10] + h_B[10] = 20, h_C[138]- not ok
[011] h_A[11] + h_B[11] = 22, h_C[139]- not ok
[012] h_A[12] + h_B[12] = 24, h_C[140]- not ok
[013] h_A[13] + h_B[13] = 26, h_C[141]- not ok
[014] h_A[14] + h_B[14] = 28, h_C[142]- not ok
[015] h_A[15] + h_B[15] = 30, h_C[143]- not ok
[016] h_A[16] + h_B[16] = 32, h_C[144]- not ok
[017] h_A[17] + h_B[17] = 34, h_C[145]- not ok
[018] h_A[18] + h_B[18] = 36, h_C[146]- not ok
[019] h_A[19] + h_B[19] = 38, h_C[147]- not ok
[020] h_A[20] + h_B[20] = 40, h_C[148]- not ok
[021] h_A[21] + h_B[21] = 42, h_C[149]- not ok
[022] h_A[22] + h_B[22] = 44, h_C[150]- not ok
[023] h_A[23] + h_B[23] = 46, h_C[151]- not ok
[024] h_A[24] + h_B[24] = 48, h_C[152]- not ok
[025] h_A[25] + h_B[25] = 50, h_C[153]- not ok
[026] h_A[26] + h_B[26] = 52, h_C[154]- not ok
[027] h_A[27] + h_B[27] = 54, h_C[155]- not ok
[028] h_A[28] + h_B[28] = 56, h_C[156]- not ok
[029] h_A[29] + h_B[29] = 58, h_C[157]- not ok
[030] h_A[30] + h_B[30] = 60, h_C[158]- not ok
[031] h_A[31] + h_B[31] = 62, h_C[159]- not ok
[032] h_A[32] + h_B[32] = 64, h_C[160]- not ok
[033] h_A[33] + h_B[33] = 66, h_C[161]- not ok
[034] h_A[34] + h_B[34] = 68, h_C[162]- not ok
[035] h_A[35] + h_B[35] = 70, h_C[163]- not ok
[036] h_A[36] + h_B[36] = 72, h_C[164]- not ok
[037] h_A[37] + h_B[37] = 74, h_C[165]- not ok
[038] h_A[38] + h_B[38] = 76, h_C[166]- not ok
[039] h_A[39] + h_B[39] = 78, h_C[167]- not ok
[040] h_A[40] + h_B[40] = 80, h_C[168]- not ok
[041] h_A[41] + h_B[41] = 82, h_C[169]- not ok
[042] h_A[42] + h_B[42] = 84, h_C[170]- not ok
[043] h_A[43] + h_B[43] = 86, h_C[171]- not ok
[044] h_A[44] + h_B[44] = 88, h_C[172]- not ok
[045] h_A[45] + h_B[45] = 90, h_C[173]- not ok
[046] h_A[46] + h_B[46] = 92, h_C[174]- not ok
[047] h_A[47] + h_B[47] = 94, h_C[175]- not ok
[048] h_A[48] + h_B[48] = 96, h_C[176]- not ok
[049] h_A[49] + h_B[49] = 98, h_C[177]- not ok
[050] h_A[50] + h_B[50] = 100, h_C[178]- not ok
[051] h_A[51] + h_B[51] = 102, h_C[179]- not ok
[052] h_A[52] + h_B[52] = 104, h_C[180]- not ok
[053] h_A[53] + h_B[53] = 106, h_C[181]- not ok
[054] h_A[54] + h_B[54] = 108, h_C[182]- not ok
[055] h_A[55] + h_B[55] = 110, h_C[183]- not ok
[056] h_A[56] + h_B[56] = 112, h_C[184]- not ok
[057] h_A[57] + h_B[57] = 114, h_C[185]- not ok
[058] h_A[58] + h_B[58] = 116, h_C[186]- not ok
[059] h_A[59] + h_B[59] = 118, h_C[187]- not ok
[060] h_A[60] + h_B[60] = 120, h_C[188]- not ok
[061] h_A[61] + h_B[61] = 122, h_C[189]- not ok
[062] h_A[62] + h_B[62] = 124, h_C[190]- not ok
[063] h_A[63] + h_B[63] = 126, h_C[191]- not ok
PASSED

원래는 32개씩 묶여서 원하는 수량대로만 돌라고
커널 코드에 if(i<N) 식으로 제한이 되어있는줄 알았는데, 없어도 의도한 대로는 돈다.
물론 돌아야 할 데이터의 갯수가 grid.x * gird.y * thread.x * thread.y 의 갯수만큼
떨어지지 않는다면 제한을 두어야겠지만 말이다.

결론 : warp은 최소단위로 묶이는 쓰레드의 갯수이긴 하지만, 실제로 그 이하로도 묶인다.
         블럭단위라고 해서 달라지는건 없는듯?
Posted by 구차니
Programming/openCL & CUDA2011. 1. 17. 22:45
CUDA Device에는 수 많은(?) 종류의 메모리가 있다.
이러한 메모리들의 특성에 대해 정리한 도표이다.
출처는 NVIDIA_CUDA_C_BestPracticesGuide.pdf 파일

의외(?)로 Local 메모리가 Local에 존재하지 않는다는 쇼킹한 이야기 -_-
쓰레드에 사용하는 메모리이지만, Off chip 즉 Device memory에 존재한다.


Posted by 구차니
Programming/openCL & CUDA2011. 1. 16. 22:11
CUDA의 kernel 부분에서 사용되는 내장변수는 다음과 같다.
아직 내용이 헷갈리지만 -_-

kernel<<<grid, thread_block>>>(vars, ... );

이런식으로 커널을 사용하는데
현재 block의 인덱스는 blockIdx에
현재 thread의 인덱스는 threadIdx에 들어간다.

blockDim 에는 전체 블럭의 카운트 값이 들어가는데
그렇다면 쓰레드의 전체 카운트 값은 어디에 들어갈려나?

아래는 Programming Guid에서 검색한 kernel 코드의 인덱스 부분
int row = blockIdx.y * blockDim.y + threadIdx.y
int col = blockIdx.x * blockDim.x + threadIdx.x;


Posted by 구차니
Programming/openCL & CUDA2011. 1. 16. 10:11
귀찮아서 CUDA 3.2 SDK만 설치하고, CUDA Toolkit 3.2는 설치하지 않고
비쥬얼 스튜디오에서 3.2용 SDK 샘플 파일을 열려고 하니 다음과 같은 에러가 발생한다.

음.. C:\Program Files\Microsoft Visual Studio 9.0\VC\VCProjectDefaults\NvCudaRuntimeApi.rules 이 파일은 머지?

머 결론은 프로젝트 파일 열수 없음 배째! 라는 건데..

3.1과 3.2의 프로젝트 파일을 비교해보니
ToolFiles의 경로가 달라졌다 -_-

부랴부랴 Toolkit 3.2를 설치하는데

경로를 바꾸니 졸라 겁준다 -_-
줸장! 내가 쫄아서 "Yes" 누르는 건 아냐 ㅠ.ㅠ

아무튼 3.2 Toolkit을 설치하고 나니 이제야 파일이 생성되고, 제대로 프로젝트 파일이 열린다.

Posted by 구차니