はじめに
浮動小数点型であるfloat/double型から整数型に変換します.
変換には,cvt命令とcvtt命令があります.
cvt命令は,MXCSRレジスタに応じて丸めを行い,cvtt命令は,常に切り捨てで丸めを行います.
_mm256_cvtepi32_ps (AVX)
__m256 _mm256_cvtepi32_ps (__m256i a)
asm: vcvtdq2ps ymm, ymm/m256
Architecture | Latency | Throughput | Uops |
---|---|---|---|
Alderlake | 4 | 0.5 | - |
Icelake | 4 | 0.5 | 1 |
Skylake | 4 | 0.5 | 1 |
Broadwell | 3 | 1 | 1 |
Haswell | 3 | 1 | 1 |
Ivy Bridge | 3 | 1 | 1 |
Sandy Bridge | 3 | 1 | 1 |
Zen3 | 3 | 0.5 | 1 |
Zen2 | 3 | 1 | 1 |
Zen | 4 | 2 | 2 |
- メモリから読み込んでもスループットは変わりません.
説明
8つの要素のintをfloatに変換します.
型を変換するだけですが,演算コストがかかります.
IntelのCPUの場合,Alderlakeを除いて浮動小数点の加算と同じコストがかかります.
AMDの場合,Zen2までは加算よりもすこしだけ重たい処理になります.
intからfloat変換はメモリからロードしてもスループットは変わりません.
_mm256_cvt|cvttps_epi32 (AVX)
__m256i _mm256_cvtps_epi32 (__m256 a)
asm: vcvtps2dq ymm, ymm/m256
__m256i _mm256_cvttps_epi32 (__m256 a)
asm: vcvttps2dq ymm, ymm/m256
CPI/Uops
Architecture | Latency | Throughput | Uops |
---|---|---|---|
Alderlake | 4 | 0.5 | - |
Icelake | 4 | 0.5 | 1 |
Skylake | 4 | 0.5 | 1 |
Broadwell | 3 | 1 | 1 |
Haswell | 3 | 1 | 1 |
Ivy Bridge | 3 | 1 | 1 |
Sandy Bridge | 3 | 1 | 1 |
Zen3 | 3 | 0.5 | 1 |
Zen2 | 3 | 1 | 1 |
Zen | 4 | 2 | 2 |
- 逆変換とパフォーマンスは同じです.
- メモリから読み込んでもスループットは変わりません.
説明
8つの要素のfloatにint変換します.
cvt命令の場合,intへの変換の場合,MXCSRコントロールレジスタの状態に合わせて浮動小数点を丸めます.
cvtt命令の場合,MXCSRコントロールレジスタの状態を無視して,常時0への切り捨てのキャストします.
つまり下記のようなキャストを行います.
double a=10.5;
int b = (int)a;
打ち切る場合も,打ち切らない場合もパフォーマンスは同じで,この逆変換とも同じです.
IntelのCPUの場合,Alderlakeを除いて浮動小数点の加算と同じコストがかかります.
AMDの場合,Zen2までは加算よりもすこしだけ重たい処理になります.
_mm256_cvtepi32_pd (AVX)
__m256d _mm256_cvtepi32_pd (__m128i a)
asm: vcvtdq2pd ymm, xmm/m128
動作
CPI/Uops
Architecture | Latency | Throughput | Uops |
---|---|---|---|
Alderlake | 7 | 1 | - |
Icelake | 7 | 1 | 2 |
Skylake | 7 | 1 | 2 |
Broadwell | 6 | 1 | 2 |
Haswell | 6 | 1 | 2 |
Ivy Bridge | 5 | 1 | 2 |
Sandy Bridge | 5 | 1 | 2 |
Zen3 | 4(≤11) | 1(0.5) | 2(1) |
Zen2 | 4(≤11) | 1(1) | 2(1) |
Zen | 7(≤14) | 2(3) | 4(7) |
- floatへの変換よりも重たいです.
- かっこつきはメモリから読み込んだ場合です.
- AIDA64: Zen L:7, T:2, Zen2 L:4, T:1, Zen3 L:4, T:0.5
- Anger: Zen L:6, T:2, Zen2 L:5, T:1, Zen3 L:6, T:1
- uopsによると,メモリから読み込むとZen3のスループットは倍になります.
- IntelのCPUは,doubleからintへの変換も同コストです.
説明
4つの要素のintをdoubleに変換します.
doubleとintのサイズが異なり,出力は2倍のサイズとなるため,引数の型は__m128i
です.
epi64からの変換ではないことに注意してください.
_mm256_cvtpd|cvttpd_epi32 (AVX)
__m128i _mm256_cvtpd_epi32 (__m256d a)
asm: vcvtpd2dq ymm, ymm/m256
__m128i _mm256_cvttpd_epi32 (__m256d a)
asm: vcvttpd2dq ymm, ymm/m256
動作
CPI/Uops
Architecture | Latency | Throughput | Uops |
---|---|---|---|
Alderlake | 7 | 1 | - |
Icelake | 7 | 1 | 2 |
Skylake | 7 | 1 | 2 |
Broadwell | 6 | 1 | 2 |
Haswell | 6 | 1 | 2 |
Ivy Bridge | 5 | 1 | 2 |
Sandy Bridge | 5 | 1 | 2 |
Zen3 | 6 | 1 | 2 |
Zen2 | 6 | 1 | 2 |
Zen | 7 | 2 | 4 |
- AIDA64 Zen L:7, T:1, Zen2 L:6.1, T:0.68 Zen3 L:6.5, T:0.43
- メモリから読み込んでも動作は変わりません.
説明
下位4つの要素のdoubleにint変換します.
cvt命令の場合,intへの変換の場合,MXCSRコントロールレジスタの状態に合わせて浮動小数点を丸めます.
cvtt命令の場合,MXCSRコントロールレジスタの状態を無視して,常時0切り捨てのキャストします.
つまり下記のようなキャストを行います.
double a=10.5;
int b = (int)a;
doubleとintのサイズが異なり,出力は半分のサイズとなるため,戻り値の型は__m128i
です.
epi64への変換ではないことに注意してください.
Zenアーキテクチャもスループットに違いはありません.