SIMT与SIMD的区别?

SIMD指令和SIMT指令有什么区别?

来源: SIMD指令和SIMT指令有什么区别?

SISD + 多核系统

在出现SIMD和SIMT之前,占主导地位的是SISD(Single instruction single data)。但很快人们发现,在一些逻辑简单但计算量大的场景下,这些计算可以并行完成。因此,直接想到的解决方案就是多块芯片并行计算,即多核系统,与此对应的编程模型是多线程编程。

SIMD

多核系统的产生使得编程变得轻松,只需解决多线程互斥、同步等一些小问题即可。但很快有人意识到,从硬件的角度看,这么做很不划算。我们只是为了并行计算,按理说只需要多块计算元件和寄存器就行了,而现在为了并行计算,甚至指令元件(如取指、译码和发射等)都有好几块,这不是浪费吗?于是,有聪明人解决了这个问题,使得一套指令部件能够带动很多套元算部件。这种硬件现在在指令集层面上体现为单条指令的操作数,从原来的几个变成了可以有很多个,即SIMD。

但是很快人们就发现了SIMD的两个痛点。第一个是高级语言不好支持,基本上都是靠在C语言里嵌入汇编来使用,这很痛苦,而且能够理解的人也不多。第二个是使用起来很不灵活,因为有时候我只需要在一部分位置进行计算,而在其他位置则不需要,这很难实现。于是,人们开始怀念多线程编程的轻松和快乐。

SIMT

之后,一家有野心的公司英伟达推出了GPU。从硬件层面看,GPU本质上与前面提到的SIMD相同,都是少量的指令部件带一大堆运算部件。但是英伟达希望能够解决SIMD的这两个痛点。首先,在指令集的设计上,指令仍然像SISD一样,几个操作数就是几元运算,只不过在执行时,调度器会给这条指令分配很多套计算元件和寄存器。这样做的第一个好处就是,这样的可执行代码可以通过一个类似高级语言多线程的编程模式编译而来,这个模式就是CUDA,从而解决了第一个痛点。在用户看来,上述的“一套运算部件和寄存器”就像一个线程一样,因此这种模式被称为SIMT。此外,英伟达还为这些指令提供了很多修饰符,比如一个Bit Mask可以指定哪些线程干活,哪些空转,这样SIMT就可以很好地支持分支语句了,从而解决了第二个痛点。

因此,总的来说,英伟达提出SIMT的初衷是希望硬件像SIMD一样高效,编程起来又像多核多线程一样轻松。
先写到这里,有人看再更新。

从硬件架构角度看,SIMT与SIMD的区别?

从硬件架构的角度来看,SIMT(Single Instruction Multiple Threads)和SIMD(Single Instruction Multiple Data)之间主要有以下几点区别:

  1. SIMT采用多线程架构,而SIMD采用多数据流架构。在SIMT中,有多个线程并行执行同一条指令,每个线程有自己独立的程序计数器和寄存器状态。在SIMD中,同一条指令作用于多个数据,通常所有执行单元共享程序计数器。
  2. SIMT支持线程级的控制流,每个线程可以根据自己的执行情况选择不同的代码路径。而SIMD中的所有执行单元必须严格同步执行相同的指令流。
  3. SIMT可以支持更多的线程(数百到数千),而SIMD的并行度一般较小(最多几十到上百)。
  4. SIMT更灵活,可以在线程级进行负载均衡。而SIMD中的执行单元不可分割,必须全部启用。
  5. SIMT需要更复杂的硬件逻辑来管理每个线程的状态。SIMD控制较简单。
  6. SIMT更适合无结构化的代码,对程序员的要求较低。SIMD需要更规整的代码结构才能发挥优势。
  7. SIMT的编程模型是线程,并行由硬件自动管理。SIMD是数据并行,需要由程序员主动编排。

综上,SIMT和SIMD作为两种并行计算架构有各自的优势,SIMT对程序员更友好,适合GPU的大规模多线程场景;而SIMD需要更规整的代码,但硬件实现上更简单高效,常用于CPU矢量运算。二者可以覆盖不同类型的并行计算需求。

从程序员角度看,SIMT与SIMD的区别?

从程序员的角度来看,SIMT和SIMD在编程模型和代码优化上也存在一些差异:

  1. SIMT采用的是线程模型,程序员主要针对线程块(block)和线程(thread)的组织来优化,利用更多线程来隐藏延迟,提高并行粒度。SIMD采用数据并行模型,程序员需要通过向量化、循环展开等方式提高数据级别的并行性。
  2. SIMT线程间可以使用 barrier 同步或者 atomic 操作通信,而SIMD通常需要程序员明确的使用缓存对齐,避免向量化时的内存数据冲突。
  3. SIMT编程可以不需要考虑硬件特性,由编译器自动优化生成设备代码。而SIMD需要充分考虑目标硬件的特点,比如向量寄存器长度,最大带宽等。
  4. SIMT更适合不规则,动态的代码,程序员主要负责算法和组织并行框架。SIMD对代码结构要求更高,程序员需要关注每一条指令是否可以向量化。
  5. SIMT对程序员的要求较低,学习曲线更平稳。而SIMD编程门槛更高,需要较强的并行编程能力。
  6. SIMT可移植性更好,同一代码可以在不同GPU架构上运行。而SIMD优化往往跟特定指令集严密相关。
  7. SIMT调试更简单,可以在CUDA中设置断点,打印日志。而SIMD需要更底层的调试。

总体来说,SIMT让GPU编程对程序员更友好,而SIMD提供了更细粒度的并行控制,但需要程序员花更多精力去优化。二者都有各自的优势,开发者可以根据场景需求选择合适的编程模型。

SIMT程序示例(CUDA SIMT)

__global__ void vectorAdd(float *a, float *b, float *c, int n) {

  int i = blockIdx.x * blockDim.x + threadIdx.x;

  if(i < n) {
    c[i] = a[i] + b[i]; 
  }

}

int main() {

  float *a, *b, *c; 
  // 分配内存

  vectorAdd<<<blocks, threads>>>(a, b, c, n);
  
  // 同步线程
  cudaDeviceSynchronize(); 

  // 释放内存

  return 0;
}

SIMD程序示例(x86 SIMD)

void vectorAdd(float *a, float *b, float *c, int n) {

  __m256 *aa = (__m256*) a;
  __m256 *bb = (__m256*) b;
  __m256 *cc = (__m256*) c;

  for(int i=0; i<n/8; i++) {
    cc[i] = _mm256_add_ps(aa[i], bb[i]); 
  }

}

int main() {
  
  float *a, *b, *c;
  // 分配内存 

  vectorAdd(a, b, c, n);

  // 释放内存

  return 0;
}

从指令集的角度看,SIMT与SIMD的区别?

从指令集的角度来看,SIMT和SIMD主要有以下几点区别:

  1. 指令并行粒度不同。SIMD的指令通常并行度较小,如128bit或256bit,一次执行几个单精度浮点运算。而SIMT可组合更多线程,一次同步执行数百条指令。
  2. 寻址模式不同。SIMD使用连续的向量寻址,同一指令操作一个向量/矩阵。SIMT允许各线程独立寻址,访问不同地址空间。
  3. 流水线不同。SIMD采用传统的重叠流水线,提高单指令吞吐。SIMT使用更宽的流水线,同时执行多指令,需要更复杂的调度和同步。
  4. 指令集特性不同。SIMD提供丰富的向量计算/转换指令。SIMT提供线程同步,通信原语。
  5. 控制流处理不同。SIMD中的所有执行单元必须严格同步。SIMT支持线程级控制流,可执行不同路径。
  6. 编译实现不同。SIMD由标准编译器优化。SIMT需要专门的设备编译器,处理复杂的线程调度和变量映射。
  7. 硬件实现不同。SIMD扩展现有指令集和流水线。SIMT需要专门的多处理器和调度器。

总结来说,SIMD和SIMT指令集各有侧重,SIMD从单指令提效,而SIMT从多线程并行着手。它们从不同方向扩展了串行指令集,提供了通用并行计算的硬件支持。

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值