并发模型

总的来说,有三种并发模型:

  • Multi-core:利用多核处理器进行基于进程或线程的并发,不同的核心可以处理不同的指令流。
  • SIMD:利用一个核心内的多个ALU单元,并发处理一个同一指令且相互独立的数据。这是一种充分利用硬件的并发形式,对于特定情况下的数据处理拥有很高的利用率。
  • Superscalar:一个核心充分利用一个指令流内的ILP指令,从而并发的处理一个指令流。

处理器模型

最简单的处理器核心的模型可以看成三个部分

  • 取指与解码器:从指令流获取指令
  • ALU:执行指令
  • 执行上下文:进程的执行环境

1.png

SIMD:single-instruction,multi-data

如一个拥有八个处理单元的核心。若数据之间是独立的,那么一个指令可以取得多个数据,然后同时处理这些数据。

2.png

如Intrinsics函数,可以用于操作SIMD指令集。

以三角函数的泰勒展开函数为例,该函数以多个因变量为输入值,输出多个结果。

  1. // sin(x) = x - x^3/3! + x^5/5! ...
  2. void sinx(int N,int terms,float* x,float *result){
  3. for(int i = 0;i < N;i++){
  4. float value = x[i];
  5. float numer = x[i] * x[i] * x[i];
  6. int denom = 6; // 3!
  7. int sign = -1;
  8. for(int j = 1;j <= terms;j++){
  9. value += sign * numer / denom;
  10. numer *= x[i] * x[i];
  11. denom *= (2*j + 2) * (2*j + 3);
  12. sign *= -1;
  13. }
  14. result[i] = value;
  15. }
  16. }

SIMD指令改进的版本如下。__m256可以以256位为指令的操作单位,在下函数中则体现为同时载入八个float元素进行运算。

3.png

SIMD的思想是对于互不相关的数据集,可以共享同一条指令。

然而,若代码中出现了分支,处理器又如何应对呢?

  1. float x = x[i];
  2. if(x > 0){
  3. // do something..
  4. }else{
  5. // do something..
  6. }
  7. result[i] = x;

多核之间可以处理不同的指令流,但是单核只能处理一条指令流。

处理器的处理方式是经过分支预测后,对于预测为真的数据集执行一种指令,否则执行另一种指令。在时间轴上,这两种是顺序执行的。

4.png

然而在分支走向不均匀,最坏情况是只有一个预测为真或只有一个预测不为真时,只有一个运算单元正在工作,其他单元都处于闲置状态。

对于SIMD来说,这种情况是应该避免出现的。

Instruction stream coherence表示指令集中,同一个指令对所有的数据集都并发地进行处理。

多核处理器

对于多核处理器来说,其拥有多个如上所述的核心,可以在不同的指令流中进行SIMD运算。

5.png


https://juejin.cn/post/6945240902625394718