Skip to content

Commit

Permalink
vault backup: 2024-12-10 16:34:52
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangfuwen authored and zhangfuwen committed Dec 10, 2024
1 parent 36770df commit b525c5f
Show file tree
Hide file tree
Showing 2 changed files with 247 additions and 7 deletions.
7 changes: 0 additions & 7 deletions Notes/001-modern-computing/024-AI芯片.md

This file was deleted.

247 changes: 247 additions & 0 deletions Notes/001-modern-computing/024-OpenGL与OpenCL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@

# OpenGL

下面一一段简单的OpenCL代码,用于绘制一个三角形:

```c

1 const char *vertexShaderSource = "#version 330 core\n"
2 "layout (location = 0) in vec3 aPos;// 位置变量的属性位置值为 0 \n"
3 "void main()\n"
4 "{\n"
5 " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
6 "}\0";
7
8 const char *fragmentShaderSource = "#version 330 core\n"
9 "out vec4 FragColor;\n"
10 "void main()\n"
11 "{\n"
12 " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);//最终的输出颜色\n"
13 "}\0";
14
15 int hello_triangle()
16 {
17 GLFWwindow* window = init_window();
18
19 ///定义着色器
20 //创建一个顶点着色器对象,注意还是用ID来引用的
21 unsigned int vertexShader;
22 vertexShader = glCreateShader(GL_VERTEX_SHADER);
23
24 //着色器源码附加到着色器对象上
25 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);//要编译的着色器对象作为第一个参数。第二参数指定了传递的源码字符串数量,这里只有一个。第三个参数是顶点着色器真正的源码,第四个参数我们先设置为NULL
26 glCompileShader(vertexShader);//编译源码
27 int success;
28 char infoLog[512];
29 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);//用glGetShaderiv检查是否编译成功
30 if (!success)
31 {
32 glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
33 std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
34 }
35
36 //创建一个片段着色器对象,注意还是用ID来引用的
37 unsigned int fragmentShader;
38 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
39 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
40 glCompileShader(fragmentShader);//编译源码
41 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);//用glGetShaderiv检查是否编译成功
42 if (!success)
43 {
44 glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
45 std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
46 }
47
48 //创建一个着色器对程序
49 unsigned int shaderProgram;
50 shaderProgram = glCreateProgram();
51 glAttachShader(shaderProgram, vertexShader);//把之前编译的着色器附加到程序对象上
52 glAttachShader(shaderProgram, fragmentShader);
53 glLinkProgram(shaderProgram);//glLinkProgram链接它们
54 glGetProgramiv(shaderProgram, GL_COMPILE_STATUS, &success);//用glGetProgramiv检查是否编译成功
55 if (!success)
56 {
57 glGetShaderInfoLog(shaderProgram, 512, NULL, infoLog);
58 std::cout << "ERROR::SHADER::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
59 }
60
61 //链接后即可删除
62 glDeleteShader(vertexShader);
63 glDeleteShader(fragmentShader);//*/
64
65 ///定义顶点对象
66 float vertices[] = {
67 -0.5f, -0.5f, 0.0f,
68 0.5f,-0.5f, 0.0f,
69 0.0f, 0.5f, 0.0f 70
71 };
72
73 //生成VAO对象,缓冲ID为VAO
74 unsigned int VAO;
75 glGenVertexArrays(1, &VAO);
76 glBindVertexArray(VAO);//绑定VAO,从绑定之后起,我们应该绑定和配置对应的VBO和属性指针,之后解绑VAO,供之后使用
77
78 //生成VBO对象,缓冲ID为VBO
79 unsigned int VBO;
80 glGenBuffers(1, &VBO);//第一个参数GLsizei是要生成的缓冲对象的数量,第二个GLuint是要输入用来存储缓冲对象名称的数组
81
82 //绑定到目标对象,VBO变成了一个顶点缓冲类型
83 glBindBuffer(GL_ARRAY_BUFFER, VBO);//第一个就是缓冲对象的类型,第二个参数就是要绑定的缓冲对象的名称
84 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//数据传入缓冲内存中,GL_STATIC_DRAW:数据不会或几乎不会改变; GL_DYNAMIC_DRAW:数据会被改变很多; GL_DYNAMIC_DRAW:数据会被改变很多
85
86 //设置顶点属性指针,如何解析顶点数据
87 /*
88 第一个参数指定我们要配置的顶点属性,顶点着色器中使用layout(location = 0)定义
89 第二个参数指定顶点属性的大小
90 第三个参数指定数据的类型
91 第四个参数定义我们是否希望数据被标准化(Normalize)。如果我们设置为GL_TRUE,所有数据都会被映射到0(对于有符号型signed数据是-1)到1之间
92 第五个参数步长(Stride),它告诉我们在连续的顶点属性组之间的间隔
93 最后一个参数的类型是void*,数据在缓冲中起始位置的偏移量(Offset)
94 */
95 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
96 glEnableVertexAttribArray(0);//启用顶点属性layout(location = 0),顶点属性默认是禁用的
97 glBindBuffer(GL_ARRAY_BUFFER, 0);//设置完属性,解绑VBO
98
99 glBindVertexArray(0);//配置完VBO及其属性,解绑VAO
100
101
102 //绘制模式为线条GL_LINE,填充面GL_FILL
103 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//正反面
104
105 while (!glfwWindowShouldClose(window))
106 {
107 processInput(window);
108
109
110 //清空屏幕
111 glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
112 glClear(GL_COLOR_BUFFER_BIT);
113
114
115 //绘制物体
116 glUseProgram(shaderProgram);//激活程序对象
117
118 glBindVertexArray(VAO);
119 //使用VAO绘制
120 glDrawArrays(GL_TRIANGLES, 0, 3);//绘制图元为三角形,起始索引0,绘制顶点数量3
121
122 glfwSwapBuffers(window);//交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲)
123 glfwPollEvents();//检查有没有触发什么事件
124 }
125
126 //释放对象
127 glDeleteVertexArrays(1, &VAO);
128 glDeleteBuffers(1, &VBO);
129
130 std::cout << "finish!" << std::endl;
131 glfwTerminate();//释放/删除之前的分配的所有资源
132 return 0;
133 }
```
代码很长,但功能很简单。它在120行每次调用glDrawArrays的时候,调用一次渲染流水线。流水线(管线)会执行一些固定的部分,也会执行两个shader,即vertex shader和fragment shader。
1. 流水线在固定的部分中将输入顶点进行一定的加工,之后会传给vertex shader,vertex shader对单个顶点进行处理,输出一个处理后的顶点。在上述代码中,vertex shader几乎没有做什么事情,它只是把每个顶点的w分量设置为1.0.这代码顶点的部分没有进行任何的变换。你也可以修改代码,给每个顶点的位置加上一些偏移,或者缩放,你会看到最终输出的图像可能就不是一个三角形了。
2. 在vertex shader之后,流水线的固定部分会将这些顶点组装成三角形,然后栅格化,根据viewport的大小,决定每个三角形中取多少个点。然后将这些点送给fragment shader。上述代码中,fragment shader也几乎没做什么事情,它只是给每个点一个固定的颜色。这样最终显示的三角形里面就被填充为这种颜色。
当技术发展到这一部分的时候,人们就发现,vertex shader和fragment shader具有一些特点:
1. 虽然要对很多点或像素(片元)进行计算,但是所做的计算的公式都是相同的,只有输入输出的数据不同。
2. vertex shader和fragment shader可以复用一部分硬件逻辑单元。
现实的计算任务中,有些任务(特别是大量数据情况下的任务)也具有计算步骤相同但数据不同的特点。所以也可以用显卡的这个单元来做这个计算。
OpenGL ES 3.0版本的时候就引入了compute shader的概念,只用来做通用计算。
compute shader的用法大概这样:
```c
char * computeShaderSource = "#version 310 es
layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout (std430, binding = 0) buffer DataBuffer {
float data[];
} buffer1;
void main() {
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
buffer1.data[pos.y * int(gl_NumWorkGroups.x) + pos.x] *= float(pos.y);
}
"
GLuint GLUtils::LoadComputeShader(const char* computeShaderSource) {
GLuint computeShader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(computeShader, 1, &computeShaderSource, NULL);
glCompileShader(computeShader);
GLint success;
glGetShaderiv(computeShader, GL_COMPILE_STATUS, &success);
if (!success) {
GLchar infoLog[512];
glGetShaderInfoLog(computeShader, 512, NULL, infoLog);
LOGCATE("GLUtils::LoadComputeShader Compute shader compilation failed: %s", infoLog);
return 0;
}
GLuint computeProgram = glCreateProgram();
glAttachShader(computeProgram, computeShader);
glLinkProgram(computeProgram);
glGetProgramiv(computeProgram, GL_LINK_STATUS, &success);
if (!success) {
GLchar infoLog[512];
glGetProgramInfoLog(computeProgram, 512, NULL, infoLog);
LOGCATE("GLUtils::LoadComputeShader Compute shader linking failed: %s", infoLog);
return 0;
}
glDeleteShader(computeShader);
return computeProgram;
}
glGenBuffers(1, &m_DataBuffer);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_DataBuffer);
float data[2][4] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(data), data, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_DataBuffer);//binding=0
// Use the program object glUseProgram (m_ProgramObj); //2x4 int numGroupX = 2; int numGroupY = 4;
glDispatchCompute(numGroupX, numGroupY, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); // 读取并打印处理后的数据
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_DataBuffer);
auto* mappedData = (float*)glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, m_DataSize, GL_MAP_READ_BIT); LOGCATE("ComputeShaderSample::Draw() Data after compute shader:\n");
for (int i = 0; i < m_DataSize/ sizeof(float); ++i) {
LOGCATE("ComputeShaderSample::Draw() => %f", mappedData[i]);
}
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
```

这段代码中的compute shader直接从storage buffer读取输入,再将输出写入到storage buffer。


# OpenCL


OpenCL是一个专门于通用计算任务的API。目前还比较尴尬。理论上来讲,它可以应用于各种各样的硬件,但实际情况是除了GPU外,支持OpenCL的硬件并不很多,使用OpenCL的开发者也比较少。

它的API接口类似于OpenGL,但是提供更精细的command queue管理,这点有点类似于vulkan。

由于开发者和硬件vendor的双重不待见,它的性能如何其实是打个问号的。所以一般是万不得已才会用。



# nVidia显卡

## RTX4090

## A100

## CUDA

# 高通平台

## Snapdragon上的GPU

## Snapdragon上的NPU


# MTK平台

# nVidia的显卡都是显卡吗?

2023前以来的大模型热导致英伟达公司热得发烫。为什么AI要用显卡来做计算呢?
A100显卡的虽然中文叫显卡,英文叫GPGPU,但其实它跟显示或Graphics已经没有太大的关系了。

A100

0 comments on commit b525c5f

Please sign in to comment.