假设我正在使用一台计算机,或多或少是任何典型的现代计算机。设备驱动程序负责我在屏幕上看到的一切,包括当我输入这些内容时屏幕的更新(这当然属于操作系统的范围,例如 Windows)。
让我们将其降低到硬件不关心是否有内核的水平,而只是接受指令。
基本上,GPU 如何“知道”如何做所有事情?驱动程序是否基本上控制每个微小的、内在的或硬件电路级的功能,或者使用驱动程序提供的特殊指令来计算要显示的二进制数据?
如果是这样,GPU 是否像 CPU 一样使用“特殊”语言或“汇编”来理解发送给它的指令?
我的知识有太多空白,而且 GPU 背后以及通过硬件直接访问它们还存在着令人不快的“秘密”。
例如,GPU 和 CPU 必须能够以某种方式连接,因此可以通过 CPU 组件和实现正确的数据/地址总线来访问 GPU。设备供应商不可能让驱动程序之外无法访问 GPU,因为驱动程序也是编译代码,而 GPU 作为可编程电路,必须使用二进制指令。
我问过这类问题,但很多网站都很快删除了,而且没有给出原因,那么这里面有什么大秘密吗?它是主板上的一个硬件,可以像其他硬件一样访问。
所以实际上......假设这是一个关于软件和硬件的“好”问题,任何人都可以直接访问 GPU 而不需要供应商特定的文件,因为这些文件并不神奇。
那么,从裸机、直接硬件的角度,在硬件特定层面上,GPU 是如何“编程”的呢?
答案1
基本上,GPU 如何“知道”如何做所有事情?驱动程序是否基本上控制每个微小的、内在的或硬件电路级的功能,或者使用驱动程序提供的特殊指令来计算要显示的二进制数据?
不是,设备有自己的 IC,可以控制设备功能的所有硬件级方面,并且它们与中央处理器交互,中央处理器可以协调设备上的各个方面,并提供更高级别的编程接口,可用于访问、读取、写入和控制设备。
如果是这样,GPU 是否像 CPU 一样使用“特殊”语言或“汇编”来理解发送给它的指令?
是也不是。与大多数设备一样,视频卡使用标准简化问题。他们使用的标准包括电子视频标准协会访问启动时视频等常规功能,或通用计算架构访问 GPU 编程函数。此外,程序可以使用机器代码(通常是编译为汇编程序的 C 语言)结合设备的编程文档(可从适配器的网站获取)直接访问非标准或设备相关的函数。
我的知识有太多空白,而且 GPU 背后以及通过硬件直接访问它们还存在着令人不快的“秘密”。
驱动程序直接访问设备,这就是它们具有特殊访问权限的原因(出于安全和稳定性原因,常规用户级程序在 Vista+ 中不允许直接访问硬件)。驱动程序使用端口、DMA(直接内存访问), 和记忆映射。
例如,GPU 和 CPU 必须能够以某种方式连接,因此可以通过 CPU 组件和实现正确的数据/地址总线来访问 GPU。设备供应商不可能让驱动程序之外无法访问 GPU,因为驱动程序也是编译代码,而 GPU 作为可编程电路,必须使用二进制指令。
驱动程序可以通过访问内存映射端口等,使用常规 CPU 指令来读写设备。举一个容易理解的例子,您可以通过向地址 B8000 处的“内存”写入内容,在文本模式下将字符显示在屏幕上。此地址不是 RAM,而是映射为与视频卡的内存相对应,因此写入该地址将写入屏幕。同样,您可以通过将要写入的字符放入注册表AL
、寄存器0x09
中AH
,然后调用 BIOS 中断来写入屏幕0x10
。更高级的功能并没有什么不同;您可以使用设备公开和记录的任何 inetrface 来读写适配器的内存、调用其芯片上的功能等等。
所以实际上......假设这是一个关于软件和硬件的“好”问题,任何人都可以直接访问 GPU 而不需要供应商特定的文件,因为这些文件并不神奇。
仅适用于符合标准的功能,但其他所有功能(即更高级的功能),您都需要查阅制造商的编程文档。
那么,从裸机、直接硬件的角度,在硬件特定层面上,GPU 是如何“编程”的呢?
通过多层:
- 晶体管等固态元件
- 低级专用集成电路 (ASIC)
- 板载处理器和芯片组
- 低级编程接口(汇编)
- 更高级别的编程接口(DirectX、OpenGL)
- 高级编程语言(C++、C#、Python 等)
答案2
我并不是计算机架构方面的天才,但我会尽我所知,从各个方面尝试解答你的问题。
设备驱动程序负责我在屏幕上看到的所有内容,包括我键入此内容时屏幕的更新(当然,这属于操作系统的范畴,例如 Windows)。
确实如此,主要是因为与 GPU 的直接交互并不容易实现。因此才开发了 DirectX 和 OpenGL 等图形框架。
这个方便的定义来自维基百科更详细地解释这一点:
设备驱动程序可充当硬件设备与使用该硬件的应用程序或操作系统之间的转换器,从而简化编程。程序员可以独立于最终用户使用的特定硬件编写更高级别的应用程序代码。
基本上,GPU 如何“知道”如何做所有事情?驱动程序是否基本上控制每个微小的、内在的或硬件电路级的功能,或者使用驱动程序提供的特殊指令来计算要显示的二进制数据?
GPU 是微处理器。因此,它们负责处理。它们处理从 CPU 馈送到适当显示器的数据(即元素的位置)。它们“知道”如何做所有事情,因为它们就是这样制造的和一大群人就向 GPU 发送数据和从 GPU 发送数据的正确方法达成了一致。
将显示驱动程序视为一个缓冲区或代理。想象一下你是一个程序窗口,用户将它向上移动。你要求 GPU 刷新显示。但当 GPU 说话时克林贡人你说火神,驱动程序接收您的命令,将其翻译给 GPU,然后 GPU 执行您的命令。
如果是这样,GPU 是否像 CPU 一样使用“特殊”语言或“汇编”来理解发送给它的指令?
从维基百科:
ARB 汇编语言是一种低级着色语言,可以将其描述为汇编语言。它由 OpenGL 架构审查委员会 (ARB) 创建,用于标准化控制硬件图形管道的 GPU 指令。
这是一个例子,请记住,各个制造商(NVIDIA、ATI)都有自己的指令集。
此外,还存在OpenCL以及许多其他方式,以某种方式直接向 GPU 编写指令。
所有这些都应该在某种程度上回答你的问题。
答案3
为了补充其他答案,您应该了解 CPU 和 GPU 编程之间存在根本区别,这涉及开放性和稳定性。
CPU 由您直接输入的机器代码控制。当您编译 C 程序时,您会得到一个字节序列,即机器代码。机器代码由指令集架构 (ISA) 控制,该架构几乎总是公开记录且寿命很长(数十年)。这就是为什么您可以将 1990 年代编译的 Windows 程序运行在现代 x86-64 CPU 上的原因。
GPU 由对其 RAM 或 I/O 地址空间的读写控制。但是,对于大多数 GPU,没有标准的命令集。制造商通常将其 GPU 的确切命令集作为商业秘密,迫使您费力猜测和逆向工程如何与 GPU 通信以使其执行有用的操作。制造商为每对(GPU、OS、API)提供一个驱动程序 - 例如,Radeon 1234 GPU 的 Windows DirectX 驱动程序、Nvidia 9786 GPU 的 Linux OpenGL 驱动程序。驱动程序将一些稳定、开放、高级 API(OpenGL 等)转换为 GPU 要执行的专有(通常是秘密的)低级命令。如果制造商拒绝发布文档并且不为您所需的环境提供驱动程序,那么您就倒霉了。
请注意,GPU 命令可以执行各种操作,例如加载代码、加载数据、启动/停止执行、定义管道、更改视频输出模式等等。命令集因显卡而异;例如,光线追踪在过去并不是一项功能;可编程着色器在某些时候并不存在。
我认为 GPU 的方法相对于 CPU 的一个优势在于,在更少的限制下,GPU 的内部架构可以彻底改变,同时依靠驱动程序进行适当的转换。例如,具有可编程计算单元的 GPU 可以模拟只有固定功能单元(变换、填充、照明等)的旧一代卡。同时,CPU 对内部微架构的变化程度有限制,因为它们最终必须使用指令流并(或多或少)表现相同(即计算相同的数字,读取/写入相同的内存位置)。
听起来可能有点愚蠢,为什么 CPU 不能有驱动程序?从某种意义上说,它们确实有;BIOS 负责在启动时将微代码加载到 CPU 中,以进行一些最后的修补。但与设备驱动程序通常所做的相比,这微不足道。真正的原因是您必须从某个地方开始。如果 CPU 需要一个非平凡的驱动程序才能发挥作用,那么谁将执行该驱动程序?它不可能是 CPU,因为它尚未初始化,而且您不知道如何与它通信。那么它将是……第二个 CPU,这毫无意义。因此,CPU 以公开已知且稳定的格式执行代码,这允许它执行更多代码来控制没有公开或稳定命令集的设备。
请注意,这并不排除 CPU 拥有硬连线内部转换器的可能性。事实上,现代 x86 CPU 将机器代码转换为私有的、内部的、类似 RISC 的格式,这些格式因代代而异;它们还具有内部流水线、重新排序、分支预测、推测和其他功能。一些内部代码变形甚至可能更为激进,例如 Via 将 x86 代码更改为 VLIW,而 Apple 芯片将 x86 代码更改为 ARM。