一、何谓高性能?
对于给定的计算任务,程序完成它所需消耗的CPU时钟周期数越少,性能就越高;反之,性能就越低。
二、如何写出高性能的程序?
1. 尽量减少完成任务所需执行的指令数。
例如,对于每次重复计算的不变的量,可以提前计算好,然后直接使用,从而消除重复计算。
2. 尽量提高访存效率。
影响内存访问效率的因素有cache不命中,TLB miss,频繁的核间cache一致性同步,跨numa内存访问等。
解决方法有:联系紧密的数据尽量放到同一cache行中,同一内存页中,若数据量太大可以使用巨页。
对于解决频繁的cache同步,可以将程序设计成让不同的核,访问独立的数据项(输出统计时再汇总)。
至于解决跨numa的问题,可以通过cpu亲和性设置将线程绑定到特定的numa节点的核上去,同时将线程的内存分配与特定numa绑定。
想省事的话,可以通过numactl来启动程序。如果自己实现的话,可以调用/usr/include/numaif.h中的相关接口,如mbind等。
另外,对于在做内存的numa绑定之前就已经分配的页,可以通过move_pages将他们移到新绑定的numa上。
当然,这都是用户态的C库接口。内核态的相关系统调用为sys_mbind,sys_move_pages。
3. 用汇编代码实现关键例程
这一般是针对性能要求非常高的场合。这种情况下,就需要用汇编代码来实现了。例如,memcpy的实现。
对指令做精心的安排。例如,以最少的指令最大的效率完成任务,避免让有互锁关系的指令相邻排布。
4. 借用硬件加速器
某些处理器,内部集成了相关的加速器,例如图像处理、hash计算、加密算法等。
借用加速器(一般通过汇编代码),可以大大提高处理性能。
5. 排除系统干扰
正在某核上运行的程序,可能受到的干扰因素有,所在核频繁受中断处理打扰,时不时的有别的任务飘到本核上来抢夺cpu资源。
对于前者,可以通过设置,将中断处理转移到别的核上去。
对于后者,可以通过隔离程序所用的cpu(通过内核命令行参数isolcpus实现。PC的话,直接修改grub配置即可)来解决。