게시글
질문&답변
2024.04.19
Warp를 동시에 돌린다는 말이 이해가 가지 않습니다.
안녕하세요. 네. 당연히 그렇게 처리 합니다. SM 1개 내의 모든 SP 들은 같은 clock 으로 동시에 실행됩니다. warp 단위로 실행 해야 하다 보니, 같은 warp 를 실행하는 32개의 SP 는 instruction 도 똑같은 것을 수행합니다. 강의에서도 한번 설명했지만, GPU 구조에서는 ALU + control unit 쪽을 줄이는 대신 갯수를 늘리는 쪽으로 설계 방향을 잡았는데, ALU 를 줄이는 데는 한계가 있고, 결국 control unit을 최대한 줄이는 방법이, 32개의 warp를 실행하는 32개의 SP가 control unit 1개의 통제를 받는 방식이고, 이러면, 이들은 동시에 똑같은 instruction을 수행하는 수 밖에 없습니다. 감사합니다.
- 0
- 1
- 58
질문&답변
2024.04.19
Thread Block 개수에 제한이 있나요?
안녕하세요. 둘다 thread block 에 대한 설명이었고, 둘다 맞는 설명입니다. kernel design 시에는 thread block 의 갯수가 거의 제한되지 않습니다. (실제로는 제한이 있지만, 매우 큰 숫자라서, 실무에서는 이쪽 제한에 걸리기 전에, memory 용량 제한 등의 다른 제한이 먼저 걸리기 때문에, 제한이 없다고 설명합니다.) 반면, SM 에서는 1개의 SM 이 동시에 실행 가능한 thread block 갯수에 제한을 걸어 두었고, 보통 32개 정도로 제한됩니다. 그래서, SM 들은 kernel 에서 실행하고 있는 매우 많은 thread block 중에서, 딱 32개만 가져와서 실행을 시작하고, 실행 중인 것이 완료되면, 완료되는 대로, 1개씩 더 가져와서, 되도록 항상 32개의 thread block이 동시 실행 상태로 운영되게 합니다. 즉, CUDA 가 관리하는 kernel 의 thread pool 에는 매우 많은 thread block 이 들어갈 수 있고, 실제로 몇 천 개, 몇 만 개의 thread block을 사용하기도 합니다. 이제 CUDA가 kernel을 실행하기 시작하면, 여러 개의 SM 들이 (보통 수십개, 많으면 수백개) 돌면서, 각각은 자기가 동시에 실행시킬 수 있는 최대 갯수 (보통 32개)만큼만 가져와서 실행합니다. 전체 thread 갯수가 아무리 커도, 1개 SM 이 동시에 실행할 수 있는 thread block은 현실적으로 제한될 수 밖에 없습니다. 감사합니다.
- 0
- 1
- 49
질문&답변
2024.04.04
#include "./common.c"오류
안녕하세요. 배포된 소스 코드의 각 파일은 내부에 #include "common.c" 를 가지고 있습니다. 즉, 컴파일 할 때, 해당 파일만 컴파일 하면 되고, common.c 가 컴파일 프로젝트에 들어가면 중복이 일어나서, 위와 같은 에러가 발생하게 됩니다. 감사합니다.
- 0
- 1
- 48
질문&답변
2024.03.28
22-6 varying color 프로그램 관련 질문
안녕하세요. 출장 관계로, 답변이 늦었습니다. ^^;; 우선, shader 변수들은 변수명으로 서로 link 됩니다. 컴파일러에서, vertex shader 의 out 에 있는 변수 이름과, fragment shader 의 in 에 있는 변수 이름이 일치하면 서로 연결 시키게 됩니다. 역으로, 서로 연결되는 변수 이름이 없다면, warning 이나, error 메시지를 출력해 줍니다. fragment shader 의 out 은 사실 draw buffer 의 설정에 따라서 달라지는데, OpenGL draw buffer 의 최초 설정은 framebuffer 의 RGBA 값으로 출력하게 되어 있어서, out vec4 fragColor 라고 하면, 그 값이 그대로 연결되는 것입니다. draw buffer 의 설정을 변경할 수 있어서, 그런 경우에는 여러 개의 RGBA 값을 출력하거나, depth 값을 출력하게 하는 것도 가능합니다. 다만, 이런 부분은 상당히 고급 기법이 되어서, OpenGL 강의의 8번 이나 9번에서 다룰 계획이었고, 지금은 7번까지 제공되고 있습니다. 추가 강의를 제작하게 되면, 해당 내용이 들어갈 것 같습니다. 감사합니다.
- 0
- 1
- 57
질문&답변
2024.03.28
32-6 OpenGL Z 버퍼 - Depth 설정 관련 질문
안녕하세요. 일종의 습관으로 볼 수 있습니다. ^^;;; 예제 프로그램들에서와 같이, 간단한 출력을 하는 경우에는, glEnable 종류를 main loop 이전에 한번 설정하는 방법이 더 나을 수 있습니다. 반면에, 꽤 복잡한 scene 을 출력할 때는, depth 처리가 필요한 것들을 출력했다가, 중간에 depth 처리가 불필요한 것을 출력했다가, 다시 depth 처리가 필요한 것을 출력했다가 하는 경우도 종종 생깁니다. 이런 부분들을 처리하다 보면, 중요한 glEnable 들은 draw 하기 바로 전에 다시 set 하는 방식을 취하기도 합니다. 다행히, glEnable 함수로 무엇을 설정하는 것이, 대부분의 경우는 크게 오버헤드가 없어서, 필요하면 중복해도 써도 별 문제가 없다 보니까, glEnable 함수를 draw 루틴에 넣어두기도 합니다. 굳이 따지면, 비효율적인것은 맞는데, 다른 책이나, 싸이트의 예제들을 보아도, draw 루틴에서, 일종의 습관처럼 써 놓는 경우가 종종 있습니다. 감사합니다.
- 0
- 1
- 47
질문&답변
2024.02.29
계산시간 비교
안녕하세요. 답변을 쓰러 왔더니, AI 인턴이 생각보다 잘 답해 주네요. ㅎㅎ 아래쪽, 중간에 나온, 기존 질문에 대한 답변을 참고하시면 더 상세하게 나올 겁니다. CUDA로 실제 프로젝트를 진행할 때, 실질적으로 제일 신경쓰는 부분이 바로, 데이터 이동을 최소화 하면서 전체 알고리즘을 돌리는 것이 됩니다. 결국 최소한 1번씩은 main memory --> CUDA memory , CUDA memory --> main memory 를 해야 하고, 그 외에는 최대한 추가 copy를 피하도록 설계하게 됩니다. 그리고, main board 의 구조에 따라서, copy 시간이 꽤 차이가 난다는 점도 고려하셔야 할 겁니다. 감사합니다.
- 0
- 2
- 99
질문&답변
2024.02.22
쉐이더에 연산 코드 선언
안녕하세요. 행렬 연선을 버텍스 쉐이더나, 심지어 프래그먼트 쉐이더에 시킬 수도 있습니다만, 쉐이더 프로그래머나, 게임 엔진 프로그래머들은 되도록... 특별히 필요한 경우가 아니면, 그렇게 하지 않으려고 합니다. 게임 엔진 프로그래머들이 극단적으로 효율성을 추구하는 경향이 있는데, 쉐이더 와 CPU 간에 누가 하면 더 빠른가를 계산해 보면, 행렬 연산은 CPU가 딱 한번 해서, 모든 쉐이더에 주는 쪽이 훨씬 효율적입니다. 예외적으로, 버텍스마다 적용해야 하는 행렬 연산이 다르거나, 특별히 프래그먼트에서 행렬 연산을 해야만 하는 특수 효과가 아니라면, 강의 시간에도 한번 설명했습니다만, CPU가 미리 계산해서 주는 쪽이 훨씬 효율적입니다. q = M1 M2 M3 q_w 와 같은, 전형적인 행렬 연산을 할때, 쉐이더 프로그램에서 저걸 해 주려면, M1, M2, M3 모두 주고, q = M1 x M2 x M3 x q_w 라는 연산을 GPU 에서, 모든 버텍스에 대해서, 1백만개의 버텍스마다 일일이 하고 있어야 합니다. (행렬 곱하기 3번씩) 동일한 계산을, (M1 x M2 x M3)를 CPU 쪽에서 한번만 한 후에, 결과만 버텍스 쉐이더에 주면, q = M x q_w 로, 행렬 연산 1번씩으로, 훨씬 줄어든 연산량을 수행하면 됩니다. 버텍스가 몇 천개 일때는 대수롭지 않은데, 전체 장면에서 몇억개의 버텍스를 다루고 있다면, 분명한 차이를 보이게 됩니다. 그래서, 왠만하면, 쉐이더 프로그램은 최대한 작고 가볍게 유지하려는 경향이 있습니다. 강의 뒷부분에 가면, 퐁 쉐이딩의 계산이나, 텍스처 매핑이 나오면서, 쉐이더 쪽에서 처리할 계산들이 점점 늘어나게 될 것입니다. ^^;; 감사합니다.
- 0
- 1
- 134
질문&답변
2024.02.22
매크로 함수를 쓴 이유
안녕하세요. 해당 부분은 매크로 함수, 인라인 함수, 보통의 함수 어느 것으로 구현해도 별 차이가 없을 겁니다. 최초에 코드 작성할 때, 매크로 함수로 선택하는 바람에, 그대로 굳었습니다. 다른 형태로 쓰셔도 문제 없을 겁니다. ^^;;; 감사합니다.
- 0
- 1
- 81
질문&답변
2024.02.20
33-3 피라미드 만들기 - face 생성 시 질문
안녕하세요. 현재, 나중에 TRIANGLES 프리머티브로 그리게 되고, 삼각형 2개를 만드려는 것 뿐이라서, 어느 vertex 에서 시작해도 문제는 없습니다. v2-v1-v4, v3-v2-v4 와 같이, 시작 vertex 를 다르게 부여해도 됩니다. 삼각형 2개가 주어진다는 것이 핵심입니다. ~ 감사합니다.
- 0
- 1
- 61
질문&답변
2024.02.16
21-8 layout 키워드 : 레지스터 개수 파악
안녕하세요. layout 을 적용하는 경우는 보통 attribute register 나 uniform register 인 경우가 많아서, 해당 register 의 갯수를 체크해 봐야 합니다. 최근의 그래픽 카드들은 보통 32개 정도는 기본으로 제공해서, 0 ~ 31 정도를 쓰면 안전한 편이고, OpenGL 스펙에 따르면, 최소16개는 제공해야 합니다. 또, 필요하다면, 프로그램에서, glGet 함수에서, MAX_VERTEX_ATTRIBS 등으로, 실제 그래픽 카드의 attribute register 갯수를 실행 시간에 체크해서, 문제가 되면, 실행을 중단하거나 할 수 있습니다. layout 키워드가 요구된 것은, 여러 명의 쉐이더 프로그래머들이 다양한 쉐이더 프로그램을 작성할 때, 의외로, 변수 명을 통일시키기가 어렵다는 점에서 시작합니다. 혼자 프로그램 짤 때야, vertex shader 에서는 out vec4 tex; 으로 보내면, fragment shader 에서는 in vec4 tex 으로 받아서, 이름을 통일 하겠다는 식으로 접근할 수 있는데, 대형 프로젝트로 갔더니, 워낙 다양한 사람들이 참여하고, 일부는 이미 작성한 코드를 그냥 써야 하는데, 매번 변수 이름을 맞추는 것도 한계가 있다 보니까, 아예, "0번 레지스터는 vec4 로 반드시 무슨 정보를 준다." 라는 식으로 통일 시키는 프로젝트 관리 방법론이 나왔고, 여기에 맞추도록 해 준 것입니다. 그리고.. 또하나.. layout 키워드가 나오게 되는 또하나의 배경은, shader program 의 소스 코드를 비공개로 하려는 시도 때문입니다. 강의 나온 스타일로 OpenGL 쉐이더 프로그램을 짜게 되면, shader program 의 소스 코드가 파일 형태로 제공되거나, exe 파일 내에 문자열로 들어 있을 겁니다. 상업용 게임 개발자나, 다른 개발자들이 shader 프로그램 자체를 비공개로 하고 싶어하는 요구가 있어서, 컴파일 까지 끝난 binary 파일만 제공하면 되는 형태로 발전했고, (OpenGL version 4.1 이후) 이 경우에는 소스 코드를 전혀 제공하지 않아도 됩니다. 다만, 이렇게 되면, attribute register 몇 번이 어느 variable 하고 결합되었는지를 알아낼 방법이 없습니다. (컴파일러가 심볼 테이블도 제거해 버릴 수 있기 때문에) 이 경우는 layout 키워드가 있어야, 특정 변수를 몇번 register에 강제 할당하고, 나중에 프로그램에서 몇번 register에 특정 데이터를 강제로 넣어주는 방법이 가능해 집니다. layout 키워드가 도입된 것이 OpenGL version 4.1 이후로, binary 파일의 사용을 허용한 것과 같은 시기였다는 점에 주목해 보면... 이런 설명도 가능합니다. ~
- 0
- 1
- 68