---
# System prepended metadata

title: SSE
tags: [elkurin-daily-note]

---

# SSE

で、SSEって何？

## Streaming SIMD Extensions
SIMDは Single Instruction Multiple Data の略で、複数のデータに対し単一の命令を適応するという並列化の型。この手法に基づく演算をベクトル演算と呼ぶこともある。  
SIMDの形式をとった命令の拡張セットの一つがSSE。整数や浮動小数点の演算命令がたくさんある。  

無印SSEが1999年に出てその後SSE2, SSE3, SSE4.1, SSE4.2として進化し、現在は移動してAVX, AVX2で進化版SIMD演算が実装されている。

### Note: 浮動小数点について
浮動小数点は1bitで符号を表し、残りの部分を指数を表現する指数部と値を表現する仮数部にいい感じに分けて数を表現している。  

実用的には単精度と倍精度の2つが使われている。  
単精度は符号1bit+指数8bit+仮数23bitの合計32bitサイズで表しており、floatがこれにあたる。  
倍精度は符号1bit+指数11bit+仮数52bitの合計64bitサイズで表しており、doubleがこれにあたる。

汎用レジスタは32bitまでしか表現できない(x86)ので、単精度は乗るが倍精度はそのままでは汎用レジスタに乗らない。  
単精度についてもx86では浮動小数点用の命令は用意されていない。  
困った。

そこでSSEをサポートしたアーキテクチャでは128bit格納できるXMMレジスタが爆誕、倍精度でも乗るようになった。

## 何が違う？
[参考](https://www.officedaytime.com/tips/simd.html)

各バージョンで何が違うのかさらってみる。

SSEではXMMレジスタを16個(64bitプロセッサ)持ち、これはxmm0~xmm15と表記されている。  
各レジスタに4個の単精度を詰め込んだり、2個の倍精度や4個の32bit整数を突っ込んだりできる。

次に命令セットを見てみる。  
SSE1の命令セットを確認すると、全て単精度になっている。一方SSE2では倍精度及び整数がサポートされている。  
ほとんどすべてSSE1で存在した命令と同じ内容を倍精度・整数でサポートしたっぽい。  
SSE3ではSSE2ほどの大きなセットの追加はないあ、絶対値・符号操作・水平加算などの算術演算が導入されている。水平加算とは同じレジスタに乗っている値同士による加算演算のこと。[PHADDW](https://www.felixcloutier.com/x86/phaddw:phaddd)などがある。  
SSE4.1, 4.2では、整数周りの未実装演算がたくさんらポートされ、ドット積・丸め込みが導入されている。

この次からAVXに転生する。  
今まで128bitのXMMレジスタだけだったが、AVXから256bitのYMMレジスタ16個に進化する。  
YMMレジスタはSEEのXMMレジスタと下位128bitを共有しており、SSEと互換性がある。  
TMMレジスタは基本的に上位下位128bitずつに別れて各レーンで動く。  
3つ4つの被演算子を指定できレジスタの内容を書き換えずに演算が実行できるようになって嬉しい。

命令セットとしては比較演算子がたくさんサポートされた。またYMM系の命令が少し増えている。  
AVX2ではFused Multiply-Addという`xy+z`を一度に行う演算が追加された。

また今度中身を詳細に見てみようと思う。