三维数学基础知识
欧拉角、矩阵、四元数表示旋转的区别和优缺点
欧拉角:定义了绕着三个坐标轴的旋转角,来确定刚体的旋转位置的方式,包括俯仰角pitch,偏航角yaw和滚动角roll;
优点是:比较直观,而且单个维度上的角度也比较容易插值;
缺点是:它不能进行任意方向的插值,而且会导致万向节死锁的问题,旋转的次序对结果也有影响。
矩阵:
优点是:不受万向节死锁的影响,可以独一无二的表达任意旋转,并且可以通过矩阵乘法来对点或矢量进行旋转变换;现在多数CPU以及所有GPU都有内置的硬件加速点积和矩阵乘法;
缺点是:不太直观,而且需要比较大的存储空间,也不太容易进行插值计算。
四元数:
好处是:能够串接旋转,能把旋转直接作用于点或者矢量,而且能够进行旋转插值。另外它所占用的存储空间也比矩阵小,四元数可以解决万向节死锁的问题。
缺点是:抽象,不易理解,因为多了一个维度。
欧拉角矩阵应用:模型矩阵、观察矩阵、投影矩阵的推导
基本概念
模型矩阵M(Model):将局部坐标变换到世界坐标;
观察矩阵V(View):将世界坐标转换为观察坐标,或者说,将物体的世界坐标,转换为在相机视角下的坐标;
投影矩阵P( ...
Cache对代码的影响
问题背景
代码片段一
12345int array[10][128];for (i = 0; i < 10; i++) for (j = 0; j < 128; j++) array[i][j] = 1;
代码片段二
12345int array[10][128];for (i = 0; i < 128; i++) for (j = 0; j < 10; j++) array[j][i] = 1;
我们假设使用的L1 Cache Line大小是64字节,采用写分配及写回策略。继续假设数组 array 内存首地址是64字节对齐。
问题分析
在有了以上背景假设后,我们先分析下片段1导致的Cache Miss / Hit情况。
当执行 array[0][0] = 1 时,Cache 控制器发现 array[0][0] 的值不在Cache中,此时发生一次 Cache Miss。然后从主存中读取 array[0][0] 到 array[0][15] 的内存值到 Cache 中。
当执行访问 array[0][1] = 1 ...
Cache的基本原理
为什么需要Cache程序是如何运行起来的
程序是运行在 RAM(随机存储器) 之中,我们称之为 main memory(主存)。当我们需要运行一个进程的时候,首先会从磁盘设备(例如,eMMC、UFS、SSD等)中将可执行程序load到主存中,然后开始执行。
在CPU内部存在一堆的通用寄存器(register)。如果 CPU 需要将一个变量(假设地址是A)加1,一般分为以下3个步骤:
CPU 从主存中读取地址 A 的数据到内部通用寄存器 x0(ARM64架构的通用寄存器之一)。
通用寄存器 x0 加1。
CPU 将通用寄存器 x0 的值写入主存。
其实现实中,CPU通用寄存器的速度(< 1ns)和主存(~ 65ns)之间存在着太大的差异。
因此,上面举例的3个步骤中,步骤1和步骤3实际上速度很慢。当CPU试图从主存中 Load / Store 操作时,由于主存的速度限制,CPU不得不等待这漫长的65ns时间。
如果我们采用更快材料制作更快速度的主存,并且拥有几乎差不多的容量, 其成本将会大幅度上升。我们试图提升主存的速度和容量,又期望其成本很低,这就有点难为人了。
因此, ...
碎玉零珠————计算机组成原理
什么是缓存(Cache)?为什么需要缓存?如何提高缓存的命中率?缓存是不是最快的?
Cache即CPU的高速缓冲存储器,是一种是用于减少处理器访问内存所需平均时间的部件;
由于CPU的计算速度远远大于从CPU向内存取数据的速度,如果每次都让CPU去内存取数据,会导致CPU计算能力的浪费,所以人们设计了缓存,CPU通过读写缓存来获取操作数,结果也通过缓存写入内存;
注意程序的局部性原理,在遍历数组时按照内存顺序访问;充分利用CPU分支预测功能,将预测的指令放到缓存中执行;此外缓存的容量和块长是影响缓存效率的重要因素。
缓存不是最快的,寄存器更快。
附 Cache 的基本原理
编译器、汇编器和链接器的基本概念编译器
编译器把高级语言翻译为机器语言
得到 hello.s 文件,这个是汇编语言程序
不同的高级语言翻译的汇编语言相同
汇编器
汇编器将 hello.s 翻译成机器语言指令,把这些指令打包成可重定位目标程序。
得到 .o 文件,是一个二进制文件,它的字节码是机器语言指令,不再是字符。前面两个阶段都还有字符。
链接器
链接器负责 .o 文件的合并。得到的是可执行目标文件。
gcc ...
进程、线程、协程之间的区别
简述进程、线程、协程的概念进程
保存在硬盘上的程序运行以后,会在内存空间里形成一个独立的内存体,这个内存体有自己独立的地址空间,有自己的堆,不同进程间可以进行进程间通信,上级挂靠单位是操作系统。一个应用程序相当于一个进程,操作系统会以进程为单位,分配系统资源(CPU 时间片、内存等资源),进程是资源分配的最小单位。
线程
线程从属于进程,也被称为轻量级进程,是程序的实际执行者。线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条- 线程并行执行不同的任务。一个线程只有一个进程。
每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。
协程
协程是伴随着主线程一起运行的一段程序。
协程与协程之间是并行执行,与主线程也是并行执行,同一时间只能执行一个协程提起协程,自然是要想到线程,因为协程的定义就是 ...