高性能编程
文章平均质量分 78
高性能编程
大隐隐于野
这个作者很懒,什么都没留下…
展开
-
SSE4.2 指令集内置函数来加速32位循环冗余校验(CRC-32)计算
纯软件实现CRC32经常是借助于查表实现的(https://pycrc.org/一个可以生成CRC C语言计算代码的工具),当计算CRC32过于频繁时可通硬件指令优化以减少对CPU的占用。目前Intel支持的用于计算CRC的有CRC32和PCLMULQDQ两个指令。CRC32指令计算的是iSCSI CRC,也就是生成多项式为0x11EDC6F41的32位CRC。使用CRC32指令的方式有2种:一种是直接使用(内联)汇编代码;其实还可以使用CRC32指令并行计算CRC32,具体见引用[2]。原创 2024-04-29 15:59:56 · 643 阅读 · 0 评论 -
无锁CAS--备份,有问题
由于CAS是一个原子操作,所以即使同时T2线程了也调用了do-while中的CAS操作,但是其判断p->_next不为空,因为T1线程已经将尾节点向后移动了,所以其只能继续执行do,将p向后移动,重新移动到尾节点继续重新判断,直到成功为止....比较并交换(compare and swap,CAS),是原子操作的一种,可用于在多线程编程中实现不被打断的数据交换操作,从而避免多线程同时改写某⼀数据时由于执行顺序不确定性以及中断的不可预知性产⽣的数据不一致问题。因此,无锁队列比使用mutex的效率要高一些。原创 2024-02-06 16:51:12 · 976 阅读 · 0 评论 -
无锁队列的实现(c语言)-备份,有问题
CAS实现的是硬件级的互斥,在线程低并发的情况下,其性能比普通互斥锁高效,但是当线程高并发的时候,硬件级互斥引入的代价与应用层的锁竞争产生的代价同样都是很大的。无锁编程不需要程序员再去考虑死锁、优先反转等棘手的问题,因此在对应用程序不太复杂,而对性能要求稍高的程序中,可以采取有锁编程。如果对有锁多线程程序有良好的设计,那么可以使程序的性能在不下降的同时,实现高并发。//因为temp可能为NULL,因此我们用P记录temp->next的值,后续会用到。对于线程无锁同步方式方式的应用,我实现了一个无锁的队列。原创 2024-02-06 16:46:48 · 414 阅读 · 0 评论 -
性能工具火焰图Flame Graphs的安装和使用方法
一、概述:火焰图(flame graph)是性能分析的利器,通过它可以快速定位性能瓶颈点。perf 命令(performance 的缩写)是 Linux 系统原生提供的性能分析工具,会返回 CPU 正在执行的函数名以及调用栈(stack)。本文介绍它的安装和基本用法。原创 2023-09-15 07:39:43 · 1277 阅读 · 0 评论 -
Linux下的sleep()和sched_yield()区别
sched_yield()的man手册描述如下:DESCRIPTION sched_yield() causes the calling thread to relinquish the CPU. The thread is moved to the end of the queue for its static priority and a new thread gets to run.RETURN VALUE On success, sched_y...原创 2020-09-29 15:00:58 · 408 阅读 · 0 评论 -
【工具】linux中用top、ps命令查看进程中的线程
在Linux上显示某个进程的线程的几种方式。方法一:PS在ps命令中,“-T”选项可以开启线程查看。下面的命令列出了由进程号为<pid>的进程创建的所有线程。1.$ ps -T -p <pid>方法二: Toptop命令可以实时显示各个线程情况。要在top输出中开启线程查看,请调用top命令的“-H”选项,该选项会列出所有Linux线程。在top运行时,你也可以通过按“H”键将线程查看模式切换为开或关。1.$ top -H要让top输出某个特定进程原创 2021-08-30 17:17:22 · 3729 阅读 · 0 评论 -
【高阶】PREFETCHh Prefetch Data Into Caches
PREFETCHhPrefetch Data Into CachesOpcode Mnemonic Description 0F 18 /1 PREFETCHT0 m8 Move data from m8 closer to the processor using T0 hint. 0F 18 /2 PREFETCHT1 m8 Move data from m8 closer to the processor using T1 hint. 0F 18原创 2021-09-02 09:59:00 · 198 阅读 · 0 评论 -
【高阶】Linux用户态程序计时统计
目前要测试一段驱动程序在ARM和X86不同款型CPU上的性能;需求是可以在任意一段代码前后进行打点N次,然后show出cycle的平均开销值(算平均值避免波动的影响);关键点为:(1)cpu上获取cycle值的方法;(2)设计结构体能够存储不同cpu core的不同事件的多次cycle开销值;一:CPU的打点方法:耗时 = 周期计数/CPU主频速率(Hz);X86:static __inline__ unsigned long long rdtsc(void){ unsi原创 2021-09-11 15:10:08 · 322 阅读 · 0 评论 -
【高阶】ARMv8/aarch64下TSC(Time Stamp Counter)读取方法
在x86架构中,我们对Time Stamp Counter (TSC) 寄存器非常熟悉,通过这个寄存器对代码执行时间的衡量可精确到CPU Cycle级别。 但在ARM/ARMv8/aarch64架构中,并没有与x86 TSC对应的寄存器和直接对应的汇编指令rdtsc。 若想在ARMv8架构中,统计计算代码执行时间达到CPU Cycle级别,也需要读取类似x86的TSC寄存器。在ARMv8中,有Performance Monitors Control Register系列寄存器,其...原创 2021-09-11 15:17:53 · 2050 阅读 · 0 评论 -
【高阶】linux内存屏障详解
在单处理器情况下,每条指令的执行都是原子性的,但在多处理器情况下,只有那些单独的读操作或写操作才是原子性的。原子的操作指的就是在执行过程中不会被别的代码所中断的操作。为了弥补这一缺点,x86提供了附加的lock前缀,使带lock前缀的读修改写指令也能原子性执行。带lock前缀的指令在操作时会锁住总线,使自身的执行即使在多处理器间也是原子性执行的。xchg指令不带lock前缀也是原子性执行,也就是说xchg执行时默认会锁内存总线。原子性操作是线程间同步的基础,linux专门定义了一种只进行原子操作的类型a原创 2021-09-14 15:39:46 · 372 阅读 · 0 评论 -
【高阶】linux内核环形缓冲区ring buffer实现原理分析
1、前言最近项目中用到一个环形缓冲区(ring buffer),代码是由linux内核的kfifo改过来的。缓冲区在文件系统中经常用到,通过缓冲区缓解cpu读写内存和读写磁盘的速度。例如一个进程A产生数据发给另外一个进程B,进程B需要对进程A传的数据进行处理并写入文件,如果B没有处理完,则A要延迟发送。为了保证进程A减少等待时间,可以在A和B之间采用一个缓冲区,A每次将数据存放在缓冲区中,B每次冲缓冲区中取。这是典型的生产者和消费者模型,缓冲区中数据满足FIFO特性,因此可以采用队列进行实现。Linux原创 2021-09-14 15:10:30 · 2809 阅读 · 0 评论 -
【高阶】一个用户态的RCU实现liburcu
由于RCU最开始是从Linux kernel里面实现的,kernel里面的实现非常依赖于整个内核的运行机制(比如Scheduler,软中断等),所以要把它port出来在用户态使用的话,难度并不小。 所幸目前已经有个开源的Userspace RCU实现——liburcu,不单只实现了RCU算法,而且有几种实现方案,从侵入式的到非侵入式的。而且这个库已经在比较多的项目中用到,比如比较出名的LTTng。liburcu提供了以下几种RCU实现:rcu-qsbr:性能最好的RCU实现,可以做到reader 0原创 2021-06-25 21:30:21 · 1225 阅读 · 1 评论 -
深入理解并行编程原理与实践
本文是《Is Parallel Programming Hard, And, If So, What Can You Do About It?》的中文翻译版《深入理解并行编程》的读书笔记(就是一些摘录整理,不想按照严格的文章进行书写,所以大佬们各取所需),虽然读书笔记一般是上传豆瓣,但是看到知乎上RCU内容很少,且自己有时从知乎上获得一些知识启发,算是回馈一下社区。由于时间不多,书没读完,内容也没贯通,后续会继续补更。原著书作者Paul E.Mckenney,是Linux RCU Maintainer,原创 2021-06-25 21:03:47 · 769 阅读 · 2 评论 -
Is Parallel Programming Hard, And, If So, WhatCan You Do About It?
Is Parallel Programming Hard, And, If So, WhatCan You Do About It?原创 2021-06-25 18:59:59 · 353 阅读 · 0 评论 -
内存屏障与缓存一致性原理分析
在应用层,关于锁的使用大家应该都很熟悉了,作用就是为了保护共享变量不被同时操作而导致无法预测的情况。然而深入到具体实现,锁仅仅只是锁定临界区吗?锁的实现其实还必须实现一个语义,也就是内存屏障。内存屏障主要用于防止指令重排而导致的无法预测的情况。代码经过编译器生成的指令并不一定都是按着我们原先的想法来生成的,可能经过优化等情况编译器进行了指令的重排,然而这些重排在执行后的结果应当是一致的。其实即使编译器不重排指令,在现代的cpu中,也常常会将指令乱序执行,所以内存屏障可以保证屏障指令前后的指令顺序。原创 2021-06-24 10:28:14 · 373 阅读 · 0 评论 -
分支预测优化之__builtin_expect
1.引言在很多源码如Linux内核、Glib等,我们都能看到likely()和unlikely()这两个宏,通常这两个宏定义是下面这样的形式。#define likely(x) __builtin_expect(!!(x), 1)#define unlikely(x) __builtin_expect(!!(x), 0)可以看出这2个宏都是使用函数__builtin_expect()实现的,__builtin_expect()函数是GCC的一个内建函数(build-in...原创 2021-06-23 15:18:23 · 190 阅读 · 0 评论 -
pthread线程私有存储空间pthread_key_t
熟悉linux线程开发的人都清楚,一个进程中的线程除了线程自己的栈和寄存器之外,其他几乎都是共享的,如果一个线程想拥有一个只属于线程自己的全局变量怎么办?线程私有存储解决了这个问题。线程私有存储的具体用法:创建一个类型为 pthread_key_t 类型的变量。调用 pthread_key_create() 来创建该变量。该函数有两个参数,第一个参数就是上面声明的 pthread_key_t 变量,第二个参数是一个清理函数,用来在线程释放该线程存储的时候被调用。该函数指针可以设成 NULL ,这样原创 2021-06-23 11:49:53 · 347 阅读 · 0 评论