私は、sqrt()関数の使用量を多く必要とするテスト用ユーティリティを作成しています。可能な最適化を掘り下げた後、C++でインラインアセンブラを試してみることにしました。コードは次のとおりです。インラインアセンブラのsqrtsdはsqrt()より高速ですか?
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
using namespace std;
volatile double normalSqrt(double a){
double b = 0;
for(int i = 0; i < ITERATIONS; i++){
b = sqrt(a);
}
return b;
}
volatile double asmSqrt(double a){
double b = 0;
for(int i = 0; i < ITERATIONS; i++){
asm volatile(
"movq %1, %%xmm0 \n"
"sqrtsd %%xmm0, %%xmm1 \n"
"movq %%xmm1, %0 \n"
: "=r"(b)
: "g"(a)
: "xmm0", "xmm1", "memory"
);
}
return b;
}
int main(int argc, char *argv[]){
double a = atoi(argv[1]);
double c;
std::clock_t start;
double duration;
start = std::clock();
c = asmSqrt(a);
duration = std::clock() - start;
cout << "asm sqrt: " << c << endl;
cout << duration << " clocks" <<endl;
cout << "Start: " << start << " end: " << start + duration << endl;
start = std::clock();
c = normalSqrt(a);
duration = std::clock() - start;
cout << endl << "builtin sqrt: " << c << endl;
cout << duration << " clocks" << endl;
cout << "Start: " << start << " end: " << start + duration << endl;
return 0;
}
私は繰り返しの数を設定し、このスクリプトを使用してこのコードをコンパイルしています、プロファイリングを開始し、そしてVIMでプロファイル出力を開きます。
#!/bin/bash
DEFAULT_ITERATIONS=1000000
if [ $# -eq 1 ]; then
echo "Setting ITERATIONS to $1"
DEFAULT_ITERATIONS=$1
else
echo "Using default value: $DEFAULT_ITERATIONS"
fi
rm -rf asd
g++ -msse4 -std=c++11 -O0 -ggdb -pg -DITERATIONS=$DEFAULT_ITERATIONS test.cpp -o asd
./asd 16
gprof asd gmon.out > output.txt
vim -O output.txt
true
出力は次のとおりです。
Using default value: 1000000
asm sqrt: 4
3802 clocks
Start: 1532 end: 5334
builtin sqrt: 4
5501 clocks
Start: 5402 end: 10903
sqrtsd
命令は16の平方根をカウントするために、唯一の3802クロックを要し、かつ
sqrt()
は5501個のクロックを要する理由
質問はありますか? 特定の命令のHW実装と関係がありますか?ありがとうございました。
CPU:
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: AuthenticAMD
CPU family: 21
Model: 48
Model name: AMD A8-7600 Radeon R7, 10 Compute Cores 4C+6G
Stepping: 1
CPU MHz: 3100.000
CPU max MHz: 3100,0000
CPU min MHz: 1400,0000
BogoMIPS: 6188.43
Virtualization: AMD-V
L1d cache: 16K
L1i cache: 96K
L2 cache: 2048K
NUMA node0 CPU(s): 0-3
はなぜ* *専用のCPUの命令は、ソフトウェアの実装よりも高速ではないでしょうか? –
'normalSqrt'はループ内で' ITERATIONS'回行うのはなぜですか(そして 'asmSqrt'は1回だけです)? – crashmstr
'asmSqrt'は' normalSqrt'compute 'ITERATIONS'ルーツの間に1つのルートを計算します...おそらくここに問題がありますか? – Holt