本书首先介绍通用处理器的架构,以及汇编和编译的技术;然后讲解 Linux 内存管理、Linux 进程管理, 以及 GDB、trace、eBPF、SystemTap 等 Linux 系统开发工具;接着通过视频编解码主流技术和 NVIDIA 计算平台 CUDA 等讨论人工智能技术在音视频领域与自然语言处理领域的应用;最后讲解标准计算平台 OpenCL 的原理、开源硬件 soDLA、Intel 神经网络异构加速芯片、SystemC 框架。
本书适合从事企业系统开发及优化的技术人员阅读,也可供计算机相关专业的师生参考。
*汇聚大量芯片开发人员的经验总结;
*涵盖处理器芯片架构、核心系统软件的设计与开发;
*兼顾计算机系统硬件和软件开发。
本书知识结构:
通用处理器的架构;
汇编和编译技术;
Linux 内核中的内存管理;
Linux 内核中的进程管理;
Linux 系统中的一些开发和调试工具;
人工智能技术和 OpenCL 编程技术;
一些基础软件开源项目;
硬件架构。
周文嘉,目前就职于某国产 AI GPU 芯片公司,曾服务于 ARM、阿里巴巴、HTC 等公司,拥有 10 年以上工作经验,主要从事系统软件开发,涵盖系统库开发、指令集优化、Linux 内核开发等,为某些开源社贡献过一定数量的补丁,担任 Free time team 创始人,致力于免费教育事业。
刘盼,目前就职于某国际芯片公司,曾服务于三星电子研究所、某自动驾驶科技公司,具有手机、汽车和芯片行业的工作经验,创办 4 万多人的极客社区—“人人都是极客”,担任某科技公司合伙人,是谷歌开发者社区优秀讲师。
王钰达,加州大学伯克利分校和伊利诺伊理工学院双硕士,目前专注于 RISC-V 工具链、NVDLA 工具链、自定义自动驾驶相关加速器芯片前端和后端设计的敏捷开发。
目 录
第 1章 通用处理器架构简介 1
1.1 综述 1
1.2 AArch64寄存器堆 2
1.2.1 通用寄存器 2
1.2.2 特殊寄存器 2
1.2.3 系统控制寄存器 2
1.2.4 处理器状态 3
1.2.5 函数调用标准 4
1.3 流水线 5
1.3.1 Cortex-A77微架构 5
1.3.2 微架构与代码优化 7
1.4 AArch64异常级别 8
1.5 内存模式 9
1.5.1 内存对齐 9
1.5.2 检查内存模式问题的工具 9
1.6 原子操作 10
1.6.1 指令介绍 10
1.6.2 原子指令使用示例 11
1.7 处理器缓存 12
1.8 系统安全增强 12
1.8.1 屏障指令 12
1.8.2 PAN 13
1.8.3 MTE 14
1.9 虚拟化 14
1.9.1 ARMv7a虚拟化扩展 14
1.9.2 ARM KVM work 15
1.9.3 ARM VHE 15
1.9.4 虚拟化的其他特性 15
1.10 更多处理器架构特性 16
1.10.1 获取处理器特性 16
1.10.2 运行时问题的深入讨论 16
1.10.3 处理器架构检测 18
1.10.4 ARMv8架构主要特性 20
1.11 主流编译器和模拟器对ARMv8 架构的支持 21
1.11.1 GCC对ARMv8架构的支持 21
1.11.2 QEMU模拟器对ARMv8架构的支持 22
第 2章 汇编与编译技术入门 23
2.1 通过C/C++学习汇编语言 23
2.1.1 位运算通用优化技巧 23
2.1.2 利用ARM的ubfiz等指令优化位操作 23
2.1.3 指令与数据保序 24
2.2 ARM64 NEON技术 24
2.2.1 NEON寄存器 25
2.2.2 调试环境 27
2.2.3 NEON编程 28
2.2.4 不同NEON开发方式的比较 37
2.2.5 SIMD优化技巧 38
2.2.6 实际案例 38
2.3 RISC-V汇编介绍 38
2.3.1 RISC-V汇编指令说明 40
2.3.2 RISC-V启动代码的分析 41
2.4 玩具编译器mini_c的实现 45
2.4.1 词法分析 45
2.4.2 语法分析 46
2.4.3 mini_c的源代码 48
2.5 LLVM简介 49
2.5.1 LLVM的代码表示 49
2.5.2 LLVM优化 50
2.6 LLVM实验代码 51
2.7 LLVM源代码 52
2.7.1 LLVM-6.0源代码编译 52
2.7.2 LLVM-12.0源代码编译 53
第3章 Linux内存管理 54
3.1 从CPU角度看内存 54
3.2 内核初始化内存 58
3.2.1 early_fixmap_init()函数 58
3.2.2 setup_machine_fdt()函数 59
3.2.3 arm64_memblock_init()函数 60
3.2.4 paging_init()函数 61
3.2.5 bootmem_init()函数 63
3.3 分区页帧分配器 67
3.3.1 伙伴算法 77
3.3.2 水位控制 84
3.3.3 内存回收 88
3.3.4 碎片页面规整 91
3.4 slab分配器及kmalloc的实现 96
3.4.1 走进slab分配器 96
3.4.2 数据结构 98
3.4.3 流程分析 100
3.4.4 kmalloc的实现 101
3.5 vmalloc()的原理和实现 103
3.5.1 数据结构 103
3.5.2 vmalloc()的实现 105
3.6 malloc()/mmap()的原理和实现 107
3.6.1 认识VMA 107
3.6.2 malloc()的实现 112
3.6.3 认识mm->brk 112
3.6.4 mmap()的实现 114
3.7 缺页异常处理 115
3.7.1 匿名页面缺页中断 120
3.7.2 文件映射缺页中断 122
3.7.3 页被交换到交换分区 123
3.7.4 写时复制 125
第4章 Linux进程管理 128
4.1 Linux对进程的描述 128
4.1.1 通过task_struct描述进程 128
4.1.2 task_struct、thread_info和内核栈的关系 129
4.1.3 如何获取当前进程 131
4.2 用户态进程/线程的创建 131
4.2.1 fork()函数 132
4.2.2 vfork()函数 134
4.2.3 pthread_create()函数 135
4.2.4 fork()函数、vfork()函数和pthread_create()函数的关系 136
4.3 do_fork()函数的实现 137
4.3.1 copy_process()函数 138
4.3.2 wake_up_new_task()函数 144
4.4 进程调度 146
4.4.1 进程的分类 146
4.4.2 与调度相关的数据结构 147
4.4.3 调度时刻 150
4.4.4 调度算法 154
4.4.5 CFS 156
4.4.6 选择下一个进程 158
4.4.7 进程上下文切换 162
4.5 多核系统的负载均衡 164
4.5.1 多核架构 164
4.5.2 CPU拓扑 165
4.5.3 调度域和调度组 169
4.5.4 CPU拓扑中调度域的初始化 172
4.5.5 何时做负载均衡 173
4.5.6 负载均衡的基本过程 174
第5章 Linux系统开发工具 177
5.1 GDB调试工具 177
5.1.1 程序调试方法 177
5.1.2 代码断点 177
5.1.3 数据断点 182
5.1.4 多线程调试 184
5.1.5 捕获当前位置 187
5.1.6 GDB的原理 191
5.1.7 coredump文件的使用 191
5.1.8 通过网络进行GDB远程调试 197
5.2 trace工具 198
5.2.1 ltrace 198
5.2.2 strace 200
5.2.3 ftrace 202
5.2.4 kprobe 206
5.3 eBPF 209
5.3.1 prog注入流程 209
5.3.2 eBPF寄存器 210
5.3.3 eBPF prog的加载流程 210
5.4 SystemTap 241
5.4.1 底层软件工程师的困境 241
5.4.2 SystemTap的出现和发展历史 241
5.4.3 关于SystemTap的两个例子 242
5.4.4 基本原理 243
5.4.5 深入了解原理 247
第6章 人工智能技术 250
6.1 视频编解码主流技术及软件框架 250
6.1.1 FFmpeg/VAAPI框架介绍 250
6.1.2 Gstreamer框架介绍 251
6.1.3 OpenCV框架介绍 253
6.2 NVIDIA计算平台CUDA 255
6.2.1 CUDA:并行化的编程模型 255
6.2.2 线程层次结构 256
6.2.3 CUDA的线程索引计算 257
6.2.4 CUDA的内存模型 258
6.2.5 CUDA用例 259
6.3 基础技术介绍 261
6.3.1 GEMM算法 261
6.3.2 Resnet 263
6.3.3 KCF算法 265
6.3.4 PyTorch&LibTorch深度学习框架 270
第7章 OpenCL的编程技术 273
7.1 GPU计算与OpenCL
介绍 273
7.1.1 什么是OpenCL 273
7.1.2 OpenCL类图 275
7.2 OpenCL架构 276
7.2.1 平台模型 277
7.2.2 执行模型 277
7.2.3 内存模型 282
7.2.4 编程模型 283
7.2.5 OpenCL总结 284
7.3 关于OpenCL的例子 285
7.4 平台、上下文、设备 295
7.4.1 OpenCL平台 295
7.4.2 设备 296
7.4.3 OpenCL上下文 298
7.5 程序对象和内核对象 300
7.5.1 程序对象 301
7.5.2 内核对象 303
7.6 缓冲区 305
7.6.1 创建内存对象 305
7.6.2 查询缓冲区信息 306
7.6.3 读、写和复制缓冲区 306
7.6.4 映射缓冲区 314
7.7 关于OpenCL的案例研究 315
7.7.1 图像颜色模型转换 315
7.7.2 图像缩放 317
7.7.3 高斯模糊 320
第8章 一些开源项目 323
8.1 ISA-L开源项目优化技巧 323
8.1.1 memory 324
8.1.2 crc 324
8.1.3 igzip 325
8.1.4 isa-l_crypto 326
8.2 OOPS-RTOS 326
8.2.1 基于硬件板的OOPS-RTOS实践 326
8.2.2 基于虚拟机的OOPS-RTOS实践 331
8.3 基于Linux内核的BiscuitOS实践 332
8.3.1 构建基于ARM64 Linux的 BiscuitOS 332
8.3.2 基于BiscuitOS的内核源代码实践 333
8.3.3 基于BiscuitOS的内核模块开发 335
8.3.4 基于BiscuitOS的应用程序开发 337
8.3.5 BiscuitOS高级实践 338
第9章 硬件架构 339
9.1 概述 339
9.2 开源硬件soDLA 339
9.2.1 FIFO模块 341
9.2.2 RDMA和WDMA模块 341
9.2.3 Retiming模块和pipe模块 342
9.2.4 CSC和CMAC模块 342
9.2.5 DMA类型的选择 344
9.3 Intel神经网络异构加速芯片 344
9.3.1 Spring Hill硬件架构 345
9.3.2 推理计算引擎ICE 346
9.3.3 DL计算网络 347
9.3.4 矢量处理器 348
9.3.5 内存架构 349
9.3.6 负载灵活及可扩展性 349
9.3.7 神经网络推理计算优化 349
9.3.8 通用神经网络优化 350
9.3.9 与硬件相关的神经网络优化 351
9.4 SystemC框架 351
9.4.1 SystemC的用途 352
9.4.2 SystemC环境搭建 353
9.4.3 一个简单的SystemC例子 354