컴퓨터 그래픽 표시에서 CPU와 GPU는 어떻게 상호 작용합니까?


58

여기에서는 OpenGL API를 기반으로 회전하는 삼각형이있는 Triangle.exe라는 작은 C ++ 프로그램의 스크린 샷을 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오

매우 기본적인 예이지만 다른 그래픽 카드 작업에도 적용 할 수 있다고 생각합니다.

그냥 궁금해서 Windows XP에서 Triangle.exe를 두 번 클릭하여 모니터에서 삼각형이 회전하는 것을 볼 때까지 전체 프로세스를 알고 싶었습니다. CPU (처음 .exe를 처리하는 CPU)와 GPU (화면에 삼각형을 출력하는 GPU)는 어떻게 상호 작용합니까?

이 회전 삼각형을 표시하는 데 관련된 것은 주로 다음과 같은 하드웨어 / 소프트웨어입니다.

하드웨어

  • HDD
  • 시스템 메모리 (RAM)
  • CPU
  • 비디오 메모리
  • GPU
  • LCD 디스플레이

소프트웨어

  • 운영 체제
  • DirectX / OpenGL API
  • 엔비디아 드라이버

누구나 설명을 위해 어떤 종류의 순서도를 사용하여 프로세스를 설명 할 수 있습니까?

모든 단계 (범위를 벗어난 추측)를 다루는 복잡한 설명이 아니라 중간 IT 담당자가 설명 할 수있는 설명이 아닙니다.

IT 전문가라고 부르는 많은 사람들이이 프로세스를 올바르게 설명 할 수 없다고 확신합니다.


GPU를 CPU의 확장으로 간주하면 딜레마가 끝날 것입니다!
KawaiKx

답변:


55

프로그래밍 측면과 구성 요소가 서로 대화하는 방법에 대해 약간 작성하기로 결정했습니다. 어쩌면 특정 지역에서 약간의 빛을 비출 것입니다.

프레젠테이션

질문에 게시 한 단일 이미지를 화면에 표시하려면 어떻게해야합니까?

화면에 삼각형을 그리는 방법에는 여러 가지가 있습니다. 간단하게하기 위해 정점 버퍼가 사용되지 않았다고 가정 해 봅시다. ( 정점 버퍼 는 좌표를 저장하는 메모리 영역입니다.) 프로그램이 단순히 그래픽 처리 파이프 라인에 모든 단일 정점 (정점은 공간의 좌표)에 대해 연속적으로 지시했다고 가정 해 봅시다.

그러나 무언가를 그리기 전에 먼저 비계를 실행해야합니다. 나중에 이유를 살펴 보겠습니다 .

// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

// Reset The Current Modelview Matrix
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity();

// Drawing Using Triangles
glBegin(GL_TRIANGLES);

  // Red
  glColor3f(1.0f,0.0f,0.0f);
  // Top Of Triangle (Front)
  glVertex3f( 0.0f, 1.0f, 0.0f);

  // Green
  glColor3f(0.0f,1.0f,0.0f);
  // Left Of Triangle (Front)
  glVertex3f(-1.0f,-1.0f, 1.0f);

  // Blue
  glColor3f(0.0f,0.0f,1.0f);
  // Right Of Triangle (Front)
  glVertex3f( 1.0f,-1.0f, 1.0f);

// Done Drawing
glEnd();

그래서 그것은 무엇을 했습니까?

그래픽 카드를 사용하려는 프로그램을 작성할 때 일반적으로 드라이버에 대한 인터페이스를 선택합니다. 드라이버에 대한 잘 알려진 인터페이스는 다음과 같습니다.

  • OpenGL
  • Direct3D
  • CUDA

이 예제에서는 OpenGL을 사용하겠습니다. 지금, 당신의 드라이버에 대한 인터페이스는 당신이 프로그램을 만들기 위해 필요한 모든 도구를 제공 무엇인가 이야기를 그래픽 카드에 (또는 드라이버를 한 후 협상 카드로).

이 인터페이스는 특정 도구 를 제공합니다 . 이 도구는 프로그램에서 호출 할 수 있는 API 형태를 취합니다 .

이 API는 위 예제에서 사용 된 것으로 보입니다. 좀 더 자세히 살펴 보자.

비계

실제로 실제 그림을 그리기 전에 설정 을 수행해야합니다 . 뷰포트 (실제로 렌더링 될 영역), 투시도 ( 세계에 카메라 ), 사용할 앤티 앨리어싱 (삼각형의 가장자리를 매끄럽게하기)을 정의해야합니다 ...

그러나 우리는 그 어떤 것도 보지 않을 것입니다. 우리는 모든 프레임 에서해야 할 일을 들여다 볼 것 입니다. 처럼:

화면 지우기

그래픽 파이프 라인은 모든 프레임에서 화면을 지우지 않습니다. 당신은 그것을 말해야 할 것입니다. 왜? 이는 이유:

여기에 이미지 설명을 입력하십시오

화면을 지우지 않으면 매 프레임마다 화면 립니다 . 우리 glClearGL_COLOR_BUFFER_BIT세트로 전화 하는 이유 입니다. 다른 비트 ( GL_DEPTH_BUFFER_BIT)는 OpenGL에 깊이 버퍼 를 지우도록 지시합니다 . 이 버퍼는 어떤 픽셀이 다른 픽셀 앞에 있는지 (또는 뒤에 있는지)를 결정하는 데 사용됩니다.

변환

여기에 이미지 설명을 입력하십시오
이미지 소스

변환은 모든 입력 좌표 (삼각형의 꼭짓점)를 가져와 ModelView 행렬을 적용하는 부분입니다. 이것은 모델 (정점)이 어떻게 회전, 축척 및 변환 (이동) 되는지 설명 하는 매트릭스입니다 .

다음으로 투영 행렬을 적용합니다. 모든 좌표를 움직여 카메라를 올바르게 향하게합니다.

이제 뷰포트 매트릭스를 사용하여 한 번 더 변형합니다. 모델 을 모니터 크기에 맞게 조정하기 위해이 작업을 수행합니다 . 이제 렌더링 준비가 된 정점 세트가 있습니다!

잠시 후에 다시 변환으로 돌아갑니다.

그림

삼각형을 그리려면 상수 를 호출 하여 OpenGL에 새 삼각형 목록 을 시작하도록 지시 glBegin하면 GL_TRIANGLES됩니다.
그릴 수있는 다른 양식들도 있습니다. 삼각 스트립 이나 삼각 팬 처럼 . 동일한 양의 삼각형을 그리려면 CPU와 GPU 간의 통신이 덜 필요하기 때문에 주로 최적화입니다.

그런 다음 각 삼각형을 구성해야하는 3 개의 정점 세트 목록을 제공 할 수 있습니다. 모든 삼각형은 3 차원 좌표를 사용합니다 (3D 공간에서와 같이). 또한 을 호출 하기 전에 호출 하여 각 정점에 색상 을 제공합니다 .glColor3f glVertex3f

3 개의 정점 (삼각형의 3 개의 모서리) 사이의 음영은 OpenGL에 의해 자동으로 계산 됩니다 . 다각형의 전체면에 걸쳐 색상을 보간합니다.

상호 작용

이제 창을 클릭하면 응용 프로그램 은 클릭을 알리는 창 메시지 만 캡처하면 됩니다. 그런 다음 원하는 프로그램에서 모든 작업을 실행할 수 있습니다.

이것은 도착 많은 당신이 당신의 3D 장면과 상호 작용 시작하고 싶어 한 번 더 어렵습니다.

먼저 사용자가 창을 클릭 한 픽셀을 명확하게 알아야합니다. 그런 다음 원근 을 고려하여 마우스 클릭 지점에서 장면으로 광선의 방향을 계산할 수 있습니다. 그런 다음 장면의 객체 가 해당 광선과 교차 하는지 계산할 수 있습니다 . 이제 사용자가 객체를 클릭했는지 알 수 있습니다.

그렇다면 어떻게 회전 시키나요?

변환

일반적으로 적용되는 두 가지 유형의 변환에 대해 알고 있습니다.

  • 매트릭스 기반 변환
  • 뼈 기반 변환

차이점은 가 단일 정점에 영향을 미친다 는 것입니다 . 행렬은 항상 같은 방식으로 그려진 모든 정점에 영향을줍니다. 예를 봅시다.

앞서 삼각형을 그리기 전에 항등 행렬 을로드했습니다 . 항등 행렬은 단순히 변환 을 전혀 제공 하지 않는 행렬입니다 . 따라서 내가 그리는 것은 내 관점에만 영향을받습니다. 따라서 삼각형이 전혀 회전하지 않습니다.

나는 지금 회전 할 경우, I합니다 (CPU)에 수학 자신을 단순히 호출 할 수 있습니다 중 하나 glVertex3f와 함께 다른 (회전) 좌표. 또는 glRotatef그리기 전에 호출하여 GPU가 모든 작업을 수행하도록 할 수 있습니다 .

// Rotate The Triangle On The Y axis
glRotatef(amount,0.0f,1.0f,0.0f);               

amount물론 고정 된 값입니다. 애니메이션 하려면 애니메이션 을 추적 amount하고 매 프레임마다 늘려야합니다.

잠깐, 모든 매트릭스 토크는 어떻게 되었습니까?

이 간단한 예제에서는 행렬을 신경 쓸 필요가 없습니다. 우리는 단순히 전화 glRotatef해서 우리 를 위해 모든 것을 처리합니다.

glRotateangle벡터 xyz 주위 의 각도 회전을 생성합니다 . 현재 행렬 ( glMatrixMode 참조 )에 glMultMatrix 가 다음 행렬을 인수로 호출 한 것처럼 현재 행렬을 대체하는 곱으로 회전 행렬을 곱합니다 .

x 2 ⁡ 1-c + cx y ⁡ 1-c-z sx z ⁡ 1-c + y s 0 y x ⁡ 1-c + z sy 2 ⁡ 1-c + cy z ⁡ 1-c-x s 0 x z ⁡ 1-c-y sy z ⁡ 1-c + x sz 2 ⁡ 1-c + c 000 00 1

고마워요!

결론

명백한 것은 OpenGL 과 많은 대화가 있다는 것 입니다. 그러나 그것은 우리에게 아무것도 말하지 않습니다 . 커뮤니케이션은 어디에 있습니까?

이 예제에서 OpenGL이 우리에게 알려주는 것은 완료되었을 때 입니다. 모든 작업에는 일정 시간이 걸립니다. 어떤 작업은 엄청나게 오래 걸리고 다른 작업은 엄청나게 빠릅니다.

GPU에 꼭짓점보내는 것은 너무 빠를 것입니다. 표현 방법조차 모르겠습니다. CPU에서 GPU로 수천 개의 정점을 보내는 것은 매 프레임마다 전혀 문제가되지 않습니다.

뷰포트의 크기에 따라 화면을 지우는 데 1 밀리 초 이상이 걸릴 수 있습니다 (일반적으로 각 프레임을 그리는 데 약 16 밀리 초의 시간이 소요됩니다). 이를 정리하기 위해 OpenGL은 제거하려는 색상의 모든 단일 픽셀을 그려야합니다. 수백만 픽셀이 될 수 있습니다.

그 외에는 그래픽 어댑터의 기능 (최대 해상도, 최대 앤티 앨리어싱, 최대 색상 깊이 등)에 대해서만 OpenGL에 요청할 수 있습니다.

그러나 특정 색상의 픽셀로 텍스처를 채울 수도 있습니다. 따라서 각 픽셀은 값을 가지며 텍스처는 데이터로 채워진 거대한 "파일"입니다. 텍스처 버퍼를 생성하여 그래픽 카드에로드 한 다음 셰이더 를로드 하고이 셰이더에 텍스처를 입력으로 사용하도록 지시하고 "파일"에 대해 매우 무거운 계산을 실행하도록 지시 할 수 있습니다.

그런 다음 계산 결과 (새로운 색상의 형태)를 새로운 텍스처로 "렌더링"할 수 있습니다.

그것이 다른 방식으로 GPU를 작동시키는 방법입니다. 나는 CUDA가 그 측면과 비슷하게 작동한다고 가정하지만 그와 함께 일할 기회는 없었습니다.

우리는 실제로 전체 주제를 약간만 만졌습니다. 3D 그래픽스 프로그래밍은 야수입니다.

여기에 이미지 설명을 입력하십시오
이미지 소스


38

이해하지 못하는 내용을 정확히 이해하기는 어렵습니다.

GPU에는 BIOS가 매핑하는 일련의 레지스터가 있습니다. 이를 통해 CPU는 GPU 메모리에 액세스하고 GPU가 작업을 수행하도록 지시합니다. CPU는 값을 해당 레지스터에 꽂아 CPU의 일부 메모리를 매핑하여 CPU가 액세스 할 수 있도록합니다. 그런 다음 명령을 해당 메모리에로드합니다. 그런 다음 CPU에 메모리에로드 된 명령어를 실행하도록 GPU에 지시하는 값을 레지스터에 씁니다.

정보는 GPU를 실행하는 데 필요한 소프트웨어로 구성됩니다. 이 소프트웨어는 드라이버와 함께 제공되며 드라이버는 CPU와 GPU 사이의 책임 분할 (두 장치에서 코드의 일부를 실행하여)을 처리합니다.

그런 다음 드라이버는 CPU가 읽고 쓸 수있는 일련의 "윈도우"를 GPU 메모리로 관리합니다. 일반적으로, 액세스 패턴은 CPU가 명령어 또는 정보를 매핑 된 GPU 메모리에 기록한 다음 레지스터를 통해 GPU에게 명령어를 실행하거나 해당 정보를 처리하도록 지시합니다. 이 정보에는 셰이더 논리, 텍스처 등이 포함됩니다.


1
설명해 주셔서 감사합니다. 기본적으로 내가 이해하지 못한 것은 CPU 명령 세트가 GPU 명령 세트와 통신하는 방법이지만 분명히 그 부분을 수행하는 드라이버입니다. 이것이 추상화 레이어의 의미입니다.
JohnnyFromBF

2
관련된 CPU 명령어 세트가 없습니다. 드라이버 및 런타임은 CUDA, OpenGL, Direct3D 등을 원시 GPU 프로그램 / 커널로 컴파일 한 다음 장치 메모리에 업로드합니다. 그런 다음 명령 버퍼는 다른 리소스와 같은 것을 참조합니다.
Axel Gneiting

2
어떤 프로그램을 참조하는지 잘 모르겠습니다 (gpu에서 실행되고 드라이버에 포함되어 있음). GPU는 주로 고정 기능 하드웨어이며, 실행되는 유일한 프로그램은 드라이버가 아닌 응용 프로그램에서 제공하는 셰이더입니다. 드라이버는 이러한 프로그램 만 컴파일 한 다음 gpu의 메모리에로드합니다.
벤 리차드

1
@ sidran32 : 예를 들어, nVidia의 Kepler 아키텍처에서 커널, 스트림 및 이벤트는 CPU가 아닌 GPU에서 실행되는 소프트웨어에 의해 생성됩니다. GPU 측 소프트웨어는 RDMA도 관리합니다. 해당 소프트웨어는 모두 드라이버에 의해 GPU 메모리에로드되고 CPU / GPU 협력 쌍의 GPU 측을 처리하는 GPU에서 "미니 OS"로 실행됩니다.
David Schwartz

@DavidSchwartz GPU 컴퓨팅 작업을 잊어 버렸습니다. 그러나 어쨌든 여전히 구현에서 쉐이더와 유사하게 작동합니다. 그러나 일반적으로 OS와 관련된 기능이 동일하지 않기 때문에 "미니 OS"라고 부르지는 않습니다. GPU는 CPU와 같이 설계되지 않았기 때문에 여전히 매우 전문적인 소프트웨어입니다.
벤 리차드

13

그냥 궁금해서 Windows XP에서 Triangle.exe를 두 번 클릭하여 모니터에서 삼각형이 회전하는 것을 볼 때까지 전체 프로세스를 알고 싶었습니다. CPU (처음 .exe를 처리하는 CPU)와 GPU (화면에 삼각형을 출력하는 GPU)는 어떻게 상호 작용합니까?

실제로 운영 체제에서 실행 파일이 실행되는 방식과 GPU에서 모니터로 해당 실행 파일이 전송되는 방식을 알고 있지만 그 사이에 무슨 일이 일어나고 있는지는 모른다고 가정 해 봅시다. 이제 하드웨어 측면을 살펴보고 프로그래머 측면 답변을 더 확장 해 보겠습니다 .

CPU와 GPU의 인터페이스는 무엇입니까?

드라이버를 사용 하여 CPU는 PCI와 같은 마더 보드 기능을 통해 그래픽 카드로 대화 하고 명령을 보내 GPU 명령을 실행 하고 GPU 메모리에 액세스 / 업데이트하며 GPU 에서 실행될 코드 등을로드 할 수 있습니다.

그러나 코드에서 하드웨어 나 드라이버와 직접 대화 할 수는 없습니다. 따라서 이것은 OpenGL, Direct3D, CUDA, HLSL, Cg와 같은 API를 통해 발생해야합니다. 전자는 GPU 명령을 실행하거나 GPU 메모리를 업데이트하는 반면, 후자는 실제로 물리 / 쉐이더 언어이므로 GPU에서 코드를 실행합니다.

CPU가 아닌 GPU에서 코드를 실행하는 이유는 무엇입니까?

CPU는 일상적인 워크 스테이션 및 서버 프로그램을 실행하는 데 능숙하지만 요즘 게임에서 볼 수있는 반짝이는 그래픽에 대해서는 많이 생각하지 않았습니다. 과거에는 소프트웨어 렌더러가 있었는데, 2D와 3D로 트릭을 수행했지만 매우 제한적이었습니다. 그래서 여기 GPU가 등장했습니다.

GPU는 그래픽에서 가장 중요한 계산 중 하나 인 Matrix Manipulation에 최적화되어 있습니다. CPU는 매트릭스 조작으로 각각의 곱셈을 하나씩 계산해야하지만 (나중에 3DNow!SSE 와 같은 것 ) GPU는 모든 곱셈을 한 번에 수행 할 수 있습니다! 병행.

그러나 병렬 계산이 유일한 이유는 아닙니다. 또 다른 이유는 GPU가 비디오 메모리에 훨씬 더 가깝기 때문에 CPU를 통해 왕복하는 것보다 훨씬 빠릅니다.

이 GPU 명령어 / 메모리 / 코드는 어떻게 그래픽을 보여줍니까?

이 모든 작업을 수행 할 수있는 하나의 누락 된 조각이 있습니다. 우리가 읽고 화면에 보낼 수있는 무언가가 필요합니다. framebuffer 를 만들어서 가능합니다 . 어떤 작업을 하든지 결국 프레임 버퍼의 픽셀을 업데이트합니다. 위치 외에 색상 및 깊이에 대한 정보도 보유합니다.

어딘가에 혈액 스프라이트 (이미지)를 그리려는 예를 보자. 먼저 트리 텍스처 자체가 GPU 메모리에로드되어 원하는 때에 쉽게 다시 그릴 수 있습니다. 다음으로 실제로 스프라이트를 어딘가에 그리려면 정점을 사용하여 스프라이트를 변환하고 (올바른 위치에 배치) 래스터 화 (3D 객체에서 픽셀로 전환) 프레임 버퍼를 업데이트 할 수 있습니다. 더 나은 아이디어를 얻으려면 Wikipedia의 OpenGL 파이프 라인 플로우 차트가 있습니다.

이것은 전체 그래픽 아이디어의 주요 요점이며 더 많은 연구는 독자에게 숙제입니다.


7

일을 단순하게 유지하려면 다음과 같이 설명하면됩니다. 일부 메모리 주소는 RAM이 아니라 비디오 카드 용으로 예약되어 있습니다 (BIOS 및 / 또는 운영 체제에서). 해당 값 (포인터)으로 기록 된 모든 데이터는 카드로갑니다. 따라서 이론적으로 모든 프로그램은 주소 범위를 아는 것만으로 비디오 카드에 직접 쓸 수 있으며 이는 예전의 방식과 정확히 일치합니다. 최신 OS에서 실제로는 비디오 드라이버 및 / 또는 그래픽 라이브러리 (DirectX, OpenGL 등)에 의해 관리됩니다.


1
-1 CPU에서 DirectX API 호출이 GPU와 통신 할 수있는 방법을 묻습니다. "드라이버 및 / 또는 DirectX에서 관리합니다" ? 또한 사용자 정의 코드 (ala CUDA)를 실행하는 방법을 설명하지 않습니다.
BlueRaja-대니 Pflughoeft

3
읽는 법을 배우십시오. RAM 대신 GPU 용으로 예약 된 특정 메모리 주소에 쓰면서 말했습니다. 그리고 이것은 당신이 모든 것을 실행할 수있는 방법을 설명합니다. 카드의 메모리 범위가 등록되어 있습니다. 이 범위에서 쓰는 모든 것은 버텍스 프로세싱을 실행하는 GPU, CUDA에 달려 있습니다.
AZ.

5

GPU는 일반적으로 DMA 버퍼에 의해 구동됩니다. 즉, 드라이버는 사용자 공간 프로그램에서 수신 한 명령을 명령 스트림 (스위치 상태, 전환 방식, 컨텍스트 전환 등)으로 컴파일 한 다음 장치 메모리에 복사합니다. 그런 다음 GPU가 PCI 레지스터 또는 유사한 방법을 통해이 명령 버퍼를 실행하도록 지시합니다.

따라서 모든 그리기 호출 등에서 발생하는 일은 사용자 공간 드라이버가 명령을 컴파일 한 다음 인터럽트를 통해 커널 공간 드라이버를 호출하고 명령 버퍼를 장치 메모리에 제출하고 GPU가 렌더링을 시작하도록 지시합니다.

콘솔에서는 특히 PS3에서 직접 모든 것을 할 수 있습니다.


0

CPU가 버스를 통해 비디오 데이터를 GPU로 보낸 다음 GPU가 표시한다고 생각합니다. 따라서 더 빠른 GPU는 CPU에서 더 많은 데이터를 처리 할 수 ​​있습니다. 이런 식으로 cpuoffload를 GPU로 처리하는 과정이 있습니다. 따라서 게임 속도가 빨라집니다.

CPU가 물건을 저장하는 RAM과 같아서 빠르게로드하고 처리 할 수 ​​있습니다. 둘 다 게임을 더 빠르게 만듭니다.

또는 사운드 카드 또는 네트 카드는 동일한 원리로 작동합니다. 즉, 데이터를 가져와 CPU 작업을 오프로드합니다.


이것은 다른 답변을 복제하고 새로운 내용을 추가하지 않습니다. 실제로 새로운 내용이 없다면 답변을 올리지 마십시오.
DavidPostill

0

나는 CPU가 정확히 그래픽 카드에게 무엇을 지시하고 있는지, 그래픽 관련 명령 (opengl 또는 direct3d 명령과 같은)이 GPU로 직접 전송되지 않는 이유는 op가 확실하지 않다고 생각합니다.

CPU는 GPU에게 렌더링 대상을 알려줍니다. 모든 명령어는 먼저 CPU를 거쳐 GPU가 실제로 렌더링을 수행하도록 설정 / 초기화됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.