程序设计中多核的影响--多核系列之三
来源:互联网 发布:淘宝助理删除仓库宝贝 编辑:程序博客网 时间:2024/05/20 10:51
1。内存对齐及cache对性能的影响
在RISC体系结构下,当数据在自然对齐的边界时内存操作更加高效。CPU在读取内存的时候,是以cache线的长度来读取的,当cache block为128bytes时, CPU每次会读取128bytes至L2 cache,如果在分配时不以128bytes对齐就会增加内存的访问次数,对程序的效率有很大的影响。
如果数据超出了cache line的长度(128bytes),确保是以cache block对齐的,这样会保证使用最少的cache block。当需要的数据没在cache中,系统将等待直到数据被读入cache。把常用的数据放在一起,可以使用最少的cache block得到需要的数据。因为L1 cache的大小是有限的,如果数据分散在许多cache block中,读不同的数据会造成把仍然需要的数据从cache中清除。
2。循环展开
当循环执行对数组的多重操作时,充分利用并行操作展开部分循环可以提高性能。
char *src, *dst;
int i;
// 32次操作,每次一个字节
for (i = 0; i < 32; i++) {
dst[i] = src[i];
}
以上代码没有采用循环展开,再看如下代码:
uint64_t *src, *dst; // Note instead of char, the type is unit64_t
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
充分利用了CPU的64bit长度,每个cycle执行load和store指令一次,就可以执行64bit数据传递。而在char类型的操作中,每个cycle只能传递8bit。
当操作大的数据块时,memset( )和memcpy( )执行的效率并不高,其实现都是byte-by-byte,并不能充分利用64bit的特性。这时,就可以改写程序,利用64bit操作并结合cache line 128-byte的特点提高程序效率。
3。 Cache 预取
从内存中读取数据到L1或L2 cache 中需要几个系统时钟。为了避免读取数据时core的等待,硬件提供了预取指令,能提前将需要的数据读至L1或L2 cache。使用预取指令主要有两个原因:
Ø 保持core处于busy状态。软件首先执行预取指令,然后进行其它处理。这样core始终处于busy,需要的数据已经提前被读至L1 cache。
Ø 优化L2 cache的使用空间。L2 cache 的大小是有限的,多核间需要最优的使用其空间。预取指令可以穿过L2 cache,直接把数据读至L1 cache。节省了L2 cache的空间,也避免了L2 cache 中仍需要的数据被重写。如果cache失效会对性能造成很大的影响。
在代码中适当的位置增加预取指令。最佳位置取决于代码的结构,在预取指令后,代码需要做一些其它工作直到预取完成。最好尽可能早地开始执行预取指令以保证需要时数据已经被读入cache中。
最好的方法是建立一个没有预取指令的原形,然后运行测试以决定在代码的什么位置加入预取会更有好处。有两种情况预取指令特别有用:
Ø 如果数据对象大于一个cache块,在处理之前预取整个数据块。
Ø 当操作一个链表的数据时,在处理一个元素时提前预取下一个元素
4。 数据存储相关的优化
1) 写缓冲
当core执行store至L2/DRAM指令时,先准备一个写buffer,当数据没在L2 cache中时(发生cache失效),以前的数据从DRAM中要读入cache。所有这些会成为系统的瓶颈。Prepare-For-Store操作用于避免不必要的DRAM读。处理两方面的性能问题:
Ø 实际的写之前建立写buffer。
Ø 防止L2 cache失效时读入以前保存的数据。
当写回L2/DRAM的数据保存至每个core的write buffer。然后发送到L2 cache,L2 cache控制器设置dirty bit,最后写dirty cache 块至DRAM。操作能避免不必要的L2 cache数据已经被设为丢弃但又需要被读取,就需要从DRAM中读回L2 cache。当使用Don’t-Write Back时,core发出命令清除掉cache block 的dirty bit。L2 cache控制器清除掉dirty bit,所以当这个cache block被换出时,就不需要再写回至DRAM。
2) core局部存储
每个core部分的L1 data cache可能被用于保存core的中间结果暂存器。用于保存频繁用到的而并不需要保存到DRAM中的局部变量。由于中间结果暂存器是局部变量,数据并不需要保存至DRAM中,这就减少了write buffer对总线的冲突。
5。spin_lock
对于一段独占某些资源访问的代码,称为临界区,如果多个core要进入临界区,需要使用lock加以保护。每个core进入临界区时,都要检查锁。对于单处理器的多线程常使用信号量来进行互斥。在多核环境里,信号量被实现为spin lock。Spin lock导致CPU进入临界区一直等待直到锁被释放。
但是spin lock有以下问题,特别是当有很多个处理器想要获得锁的时候:
Ø 不能使每个核公平地访问临界区,有的核可能会处于饥饿状态。
Ø 不能保证进入临界区的次序,只能是无序地访问。
Ø 当获取锁的时候,多个核只能只能等待,而不能做其它工作。
Ø 每个核获得锁的时间没办法保证,有的核可能一直处于等待状态,很久没能得到锁。
Ø 当核的数目很多时,对于锁的竞争会更激烈,以至于各个核都会很少有机会获得锁。
如何优化spin_lock的性能,也是在程序设计中应该考虑的问题。
上一篇:软件并行模型--多核系列之二
下一篇:QEMU - Running Debian in Debian
- Linux串口(serial、uart)驱...
- C程序设计语言学习--导言(4)...
- C程序设计语言学习--导言(3)...
- C程序设计语言学习--导言(2)...
- 海南三亚政府欲烧毁家私城上亿...
- linux守护进程的几个关键地方...
- stagefright与opencore对比
- 嵌入式Linux之我行——u-boot-...
- 嵌入式Linux之我行——内核、...
- android的logcat详细用法
- ARM常见问题
- Linux操作系统原理与应用(陈...
- 简单字符设备驱动程序...
- 自己学着写lcd入门级驱动程序...
- Linux2.6.35下s3c64xx/spi子系...
- 程序设计中多核的影响--多核系列之三
- 多核计算与程序设计 - 03 基础知识 之三 线程的安全退出
- 基于Intel Parallel Advisor的多核程序设计方法--多核3
- Amdahl在多核时代的影响
- Amdahl定律对多核技术的影响
- AMDAHL定理在多核时代的影响
- 多核的网络游戏服务器开发 之 网络库(三)
- 多核
- 多核
- Intel多核程序设计培训的基本体系
- 多核时代对并发程序设计的探索
- 对一次多核程序设计比赛的总结
- iPad app应用开发系列文章之三 -- iOS的多核编程和内存管理
- iPad app应用开发系列文章之三 -- iOS的多核编程和内存管理
- 多核程序设计技术》读后感
- 多核程序设计书目
- OpenMP多核程序设计
- 多核计算与程序设计
- Bash 字符串
- linux C char colors
- kernel_debug
- 多核体系概述--多核系列之一
- 软件并行模型--多核系列之二
- 程序设计中多核的影响--多核系列之三
- QEMU - Running Debian in Debian
- c 语言中的宏,井号,可变参数
- Some interesting C problems
- 利用ftrace调试内核
- vim multifile edit
- vim diff two files
- Use clonezilla to clone and restore disk
- Bash check IP and port