C++ arcsin和arccos通常是如何实现的?
我正在阅读Agner的x86和x87汇编代码列表,注意到Arcin或arccos没有操作代码,只有arctan。所以我已经用Google和所有的结果使用ATAN和SqRT实现了这意味着ACOS和ASIN应该比ATAN慢得多,因为你需要一个额外的Sqt,但是我在C++中写了一个简单的测试程序,ACOS和asin都比ATAN:快。C++ arcsin和arccos通常是如何实现的?,c++,performance,assembly,x86,trigonometry,C++,Performance,Assembly,X86,Trigonometry,我正在阅读Agner的x86和x87汇编代码列表,注意到Arcin或arccos没有操作代码,只有arctan。所以我已经用Google和所有的结果使用ATAN和SqRT实现了这意味着ACOS和ASIN应该比ATAN慢得多,因为你需要一个额外的Sqt,但是我在C++中写了一个简单的测试程序,ACOS和asin都比ATAN:快。 #include <chrono> #include <cmath> #include <iostream> class timer
#include <chrono>
#include <cmath>
#include <iostream>
class timer {
private:
decltype(std::chrono::high_resolution_clock::now()) begin, end;
public:
void
start() {
begin = std::chrono::high_resolution_clock::now();
}
void
stop() {
end = std::chrono::high_resolution_clock::now();
}
template<typename T>
auto
duration() const {
return std::chrono::duration_cast<T>(end - begin).count();
}
auto
nanoseconds() const {
return duration<std::chrono::nanoseconds>();
}
void
printNS(char const* str) const {
std::cout << str << ": " << nanoseconds() << std::endl;
}
};
int
main(int argc, char**) {
timer timer;
double p1 = 0 + 0.000000001;
double acc1{1};
timer.start();
//less than 8 seconds
for(int i{0}; 200000000 > i; ++i) {
acc1 += std::acos(i * p1);
}
timer.stop();
timer.printNS("acos");
timer.start();
//less than 8 seconds
for(int i{0}; 200000000 > i; ++i) {
acc1 += std::asin(i * p1);
}
timer.stop();
timer.printNS("asin");
timer.start();
//more than 12 seconds
for(int i{0}; 200000000 > i; ++i) {
acc1 += std::atan(i * p1);
}
timer.stop();
timer.printNS("atan");
timer.start();
//almost 20 seconds
for(int i{0}; 200000000 > i; ++i) {
acc1 += std::atan2(i * p1, i * p1);
}
timer.stop();
timer.printNS("atan");
std::cout << acc1 << '\n';
}
#包括
#包括
#包括
班级计时器{
私人:
decltype(std::chrono::high_resolution_clock::now())开始,结束;
公众:
无效的
开始(){
begin=std::chrono::高分辨率时钟::现在();
}
无效的
停止(){
end=std::chrono::高分辨率时钟::现在();
}
模板
汽车
持续时间()常数{
返回std::chrono::duration_cast(end-begin).count();
}
汽车
纳秒()常数{
返回持续时间();
}
无效的
printNS(字符常量*str)常量{
标准::cout i;++i){
acc1+=std::atan2(i*p1,i*p1);
}
timer.stop();
timer.printNS(“atan”);
std::cout现代数学库不使用x87指令,因为它们比直接实现慢。也就是说,在现代处理器上,fsqrt
非常快,只有4个周期,所以这并不重要。@fuz:fsqrt
不是“复杂”的微代码x87指令。它是“基本”指令之一与div/mul/add/sub一起执行的操作,甚至SSE/AVX都实现了(sqrtsd
),这可能需要有一个的副本。如果你想看到asm,你实际上是微边界的,很明显,通过调试器单步进入其中一个函数调用。你没有告诉用户你正在使用什么操作系统、编译器或CPU微体系结构。不同的操作系统有不同的复杂函数的数学库实现。我是v因为这个问题确实需要操作系统、精确的CPU、编译器、所用的库等,所以我们不打算把这个问题作为离题题来结束。这个问题可能是重复的,但它肯定不是上面链接的三个问题中的任何一个的重复,它们都不涉及反触发函数。而且几乎所有链接问题的答案都是错误的——不是实际的生产C++执行与原泰勒级数的正弦和余弦,例如,尽管第二个问题的答案大部分是。现代数学库不使用X87指令,因为它们比直接实现慢,也就是说,<代码> FQRT < /代码>在现代处理器上只有4个周期,所以它非常快,所以没什么大不了的。@fuz:fsqrt
不是一条“复杂”的微代码x87指令。它是与div/mul/add/sub一起的“基本”操作之一,甚至SSE/AVX都实现了(sqrtsd
),这可能需要有一个的副本。如果你想看到asm,你实际上是微边界的,很明显,通过调试器单步进入其中一个函数调用。你没有告诉用户你正在使用什么操作系统、编译器或CPU微体系结构。不同的操作系统有不同的复杂函数的数学库实现。我是v因为这个问题确实需要操作系统、精确的CPU、编译器、所用的库等,所以我们不打算把这个问题作为离题题来结束。这个问题可能是重复的,但它肯定不是上面链接的三个问题中的任何一个的重复,它们都不涉及反触发函数。而且几乎所有链接问题的答案都是错误的——不是实际生产C++执行与正弦泰勒级数的正弦和余弦,例如,尽管第二个问题的答案最多。