绿皮小火车

随着现在高铁,动车以及飞机的日益普及,小时候经常乘坐的绿皮小火车基本已经销声匿迹了。今年春节,我有幸又坐了一次绿皮小火车。

这趟绿皮小火车的管理比较松散,可以直接上车,然后再补票。其次由于需要站站停靠,所以运行时间也要多将近一倍,但相应的票价也便宜,为同样里程票价的一半。火车上的开水间使用的还是烧煤的锅炉,打热水需要自己拿钥匙打开锅炉房,这个也是我第一次见到。

如果你对火车运行时间没有要求,并且也不介意小火车上简陋的环境,我建议有机会可以试着体验一次这种绿皮小火车,因为它会带给你不一样的感觉和记忆。

Concurrency(并发)和Parallelism(并行)的解释

今天看到一个对Concurrency(并发)和Parallelism(并行)这两个术语的一个解释,感觉很精确。记录在此,以供日后查阅(原文在这里):

Concurrency and parallelism are two related but distinct concepts.

Concurrency means, essentially, that task A and task B both need to happen independently of each other, and A starts running, and then B starts before A is finished.

There are various different ways of accomplishing concurrency. One of them is parallelism--having multiple CPUs working on the different tasks at the same time. But that's not the only way. Another is by task switching, which works like this: Task A works up to a certain point, then the CPU working on it stops and switches over to task B, works on it for a while, and then switches back to task A. If the time slices are small enough, it may appear to the user that both things are being run in parallel, even though they're actually being processed in serial by a multitasking CPU.  

Concurrency(并发)是指系统上的多个task(任务)之间由于没有任何依赖关系,所以可以同时运行。以两个taskAB),两核CPUAB)系统为例,如果在一个时间点上,task ACPU A上运行,而task BCPU B上运行,我们就可以称这两个taskParallelism(并行)运行的。对单核CPU来说,由于在一个时间点上只能执行一个task,所以这两个task只能是Sequential(串行)运行的。

一句话总结,Concurrency(并发)描述了task之间的逻辑关系(能否同时运行),而Parallelism则描述了task运行时的真正状态(是否真的在同时运行)。

Perf笔记(二)

Perf_events所处理的hardware event(硬件事件)需要CPU的支持,而目前主流的CPU基本都包含了PMUPerformance Monitoring Unit,性能监控单元)。PMU用来统计性能相关的参数,像cache命中率,指令周期等等。由于这些统计工作是硬件完成的,所以CPU开销很小。

X86体系结构为例,PMU包含了两种MSRsModel-Specific Registers,之所以称之为Model-Specific,是因为不同modelCPU,有些register是不同的):Performance Event Select RegistersPerformance Monitoring CountersPMC)。当想对某种性能事件(performance event)进行统计时,需要对Performance Event Select Register进行设置,统计结果会存在Performance Monitoring Counter中。

perf_events工作在采样模式(samplingperf record命令即工作在这种模式)时,由于采样事件发生时和实际处理采样事件之间有时间上的delay,以及CPU流水线和乱序执行等因素,所以得到的指令地址IP(Instruction Pointer)并不是当时产生采样事件的IP,这个称之为skid。为了改善这种状况,使IP值更加准确,Intel使用PEBSPrecise Event-Based Sampling),而AMD则使用IBSInstruction-Based Sampling)。

PEBS为例:每次采样事件发生时,会先把采样数据存到一个缓冲区中(PEBS buffer),当缓冲区内容达到某一值时,再一次性处理,这样可以很好地解决skid问题。

执行一下perf list --help命令,会看到下面内容:

The p modifier can be used for specifying how precise the instruction address should be. The p modifier can be specified multiple times:

       0 - SAMPLE_IP can have arbitrary skid
       1 - SAMPLE_IP must have constant skid
       2 - SAMPLE_IP requested to have 0 skid
       3 - SAMPLE_IP must have 0 skid

For Intel systems precise event sampling is implemented with PEBS which supports up to precise-level 2.

现在可以理解,经常看到的类似“perf record -e "cpu/mem-loads/pp" -a”命令中,pp就是指定IP精度的。

Perf笔记(一)

Perf_events是目前在Linux上使用广泛的profiling/tracing工具,除了本身是内核(kernel)的组成部分以外,还提供了用户空间(user-space)的命令行工具(“perf”,“perf-record”,“perf-stat”等等)。

perf_events提供两种工作模式:采样模式(sampling)和计数模式(counting)。“perf record”命令工作在采样模式:周期性地做事件采样,并把信息记录下来,默认保存在perf.data文件;而“perf stat”命令工作在计数模式:仅仅统计某个事件发生的次数。

我们经常看到类似这样的命令:“perf record -a ...... sleep 10”。在这里,“sleep”这个命令相当于一个“dummy”命令,没有做任何有意义的工作,它的作用是让“perf record”命令对整个系统进行采样,并在10秒后自动结束采样工作。

“Retired Instruction”的含义

最近在读intel CPU相关文档时,看到一个词:“Retired Instruction”,不知道该作何解释。上网google到这篇网页,理解含义应该是:因为执行每个指令要花多个时钟周期,并且CPU存在流水线,乱序执行等问题,“Retired Instruction”就是指在一个时间点上,已经确定执行完成的指令。

MiB(Mebibyte)和 MB(Megabyte)

上周五和同事讨论问题时,自己才知道不仅有MBMegabyte),还有MiBMebibyte)。说来惭愧,以前看到同事ppt提到MiB,还以为是笔误呢。简单来讲,1MiB包含1024^2 bytes,自从MiB出现后,1MB更倾向于表示1000^2 bytes。同样道理,现在也有KibibyteGibibyte

参考资料:
What is the difference between 1 MiB and 1 MB and why should we care?
Mebibyte

STREAM项目简介

STREAM是一个度量内存带宽(memory bandwidth)的项目(项目主页在这里:http://www.cs.virginia.edu/stream/),程序通过重复地执行几个简单的数学运算,来测量内存的访问带宽。代码有CFORTRAN两种语言版本。在这里,我对C语言程序版本做个简单介绍:

(1)C代码很简单,只有一个文件。一共才500多行,还包含了很多注释。默认情况下,测试数组的数据类型是double
(2)表示数组长度的STREAM_ARRAY_SIZE要足够大。代码注释提到,要让数组所占内存的大小满足两个条件:
a)至少是cache大小的3.8~4倍。这样做的原因应该是保证每次访问数组元素一定是从内存中访问,而不是cache
b)至少要让时间校准的代码输出大于20tick。这样做的原因应该是保证让程序执行一个足够长的时间。
(3)checktick()函数用来得到系统1个tick所占用的微秒数(us),也就是系统最小的时钟精度。
(4)默认情况下,编译出的可执行程序是单线程的。如果想编译多线程程序,可以在编译时指定OPENMP编译选项。请参考FAQMultiprocessor Runs一节(http://www.cs.virginia.edu/stream/ref.html)。