죄와 cos를 함께 계산하는 가장 빠른 방법은 무엇입니까?


100

값의 사인과 코사인을 함께 계산하고 싶습니다 (예 : 회전 행렬 생성). 물론 a = cos(x); b = sin(x);, 처럼 하나씩 하나씩 따로 계산할 수 는 있지만 두 값이 모두 필요할 때 더 빠른 방법이 있는지 궁금합니다.

편집 : 지금까지 답변을 요약하려면 :

  • VladFSINCOS두 가지를 모두 계산하는 asm 명령이 있다고 말했습니다(FSIN혼자호출과 거의 동시에)

  • Chi가 알아 차린 것처럼 ,이 최적화는 때때로 컴파일러에 의해 이미 수행됩니다 (최적화 플래그를 사용할 때).

  • 카페는 기능이 있음을 지적sincos하고sincosf아마 가능하며 단지 포함하여 직접 호출 할 수 있습니다math.h

  • 조회 테이블을 사용하는 tanascius 접근 방식은 논란의 여지가 있습니다. (그러나 내 컴퓨터와 벤치 마크 시나리오에서는sincos32 비트 부동 소수점에 대해 거의 동일한 정확도보다 3 배 빠르게 실행됩니다.)

  • Joel Goodwin 은 매우 정확한 근사화 기법에 대한 흥미로운 접근 방식에 연결했습니다 (저에게는 테이블 조회보다 훨씬 빠릅니다).


1
sin / cos의 기본 구현에 대한이 질문도 참조하십시오. stackoverflow.com/questions/1640595
Joel Goodwin

1
시도 sinx ~ x-x^3/6cosx~1-x^2/4근사치로 당신은 정확성보다는 속도에 대해 걱정합니다. 정확도에 더 많은 가중치를두면 두 시리즈 중 하나에 용어를 추가 할 수 있습니다 ( en.wikipedia.org/wiki/Taylor_series 아래로 스크롤하여 trig taylor 시리즈로 스크롤합니다.) 이는 시간이 다른 원하는 함수를 근사화하는 일반적인 방법 n입니다. 따라서 사인과 코사인이 속한 더 큰 함수가 있다면 sin 대신에 근사하면 훨씬 더 큰 속도를 얻을 수 있습니다 .cos는 독립적입니다.
ldog 2010-04-23

이것은 정확도가 매우 낮은 불량한 기술입니다. Joel Goodwin의 게시물을 참조하십시오. Taylor 시리즈는 아래에 게시되었습니다. 답변으로 게시 해주세요.
Danvil

1
그것은 당신의 요구 사항에 따라 다릅니다. 정확도를 원한다면 Taylor 시리즈는 어떤 점 에 가까운 값이 필요한 경우에만 좋은 근사치 가 될 것입니다. 그러면 0 대신 Taylor 시리즈를 확장하십시오. 이것은 가까운 곳에서 우수한 정확도를 제공 하지만 멀리 갈수록 결과가 더 나빠집니다. 주어진 asnwer를보고 .NET에서 멀리 떨어진 값에 대해 시도했을 때 정확도가 좋지 않다고 생각했을 것입니다 . 그 대답은 sin, cos는 0 주위로 확장되었습니다.xx_0x_0x_00
ldog

답변:


52

최신 Intel / AMD 프로세서에는 FSINCOS사인 및 코사인 함수를 동시에 계산하는 명령 이 있습니다. 강력한 최적화가 필요한 경우이를 사용해야합니다.

다음은 작은 예입니다. http://home.broadpark.no/~alein/fsincos.html

다음은 MSVC의 다른 예입니다. http://www.codeguru.com/forum/showthread.php?t=328669

다음은 또 다른 예입니다 (gcc 사용) : http://www.allegro.cc/forums/thread/588470

그들 중 하나가 도움이되기를 바랍니다. (이 지침을 직접 사용하지 않았습니다.)

프로세서 수준에서 지원되므로 테이블 조회보다 훨씬 빠를 것으로 기대합니다.

편집 :
WikipediaFSINCOS387 프로세서에 추가 되었다고 제안 하므로 지원하지 않는 프로세서를 거의 찾을 수 없습니다.

편집 :
인텔의 문서에 따르면 부동 소수점 분할 FSINCOS보다 약 5 배 정도 느립니다 FDIV.

편집 :
모든 최신 컴파일러가 사인 및 코사인 계산을 FSINCOS. 특히 내 VS 2008은 그렇게하지 않았습니다.

편집 :
첫 번째 예제 링크는 죽었지 만 Wayback Machine에 여전히 버전있습니다 .


1
@phkahler : 그거 좋겠네요. 이러한 최적화가 최신 컴파일러에서 사용되는지 여부는 알 수 없습니다.
Vlad

12
fsincos명령은 없다 "매우 빠르게". 인텔의 자체 최적화 매뉴얼에는 최근 마이크로 아키텍처에서 119 ~ 250 사이클이 필요하다고 인용되어 있습니다. 비교에 의해 (ICC와 함께 배포) 인텔의 수학 라이브러리는 수 별도로 계산 sincosx87 장치 대신 SSE를 사용하는 소프트웨어 구현을 사용하여, 100 개 미만 사이클이다. 두 가지를 동시에 계산 한 유사한 소프트웨어 구현은 여전히 ​​더 빠를 수 있습니다.
Stephen Canon

2
@Vlad : ICC 수학 라이브러리는 오픈 소스가 아니며 재배포 할 수있는 라이선스가 없어 어셈블리를 게시 할 수 없습니다. sin그러나 그들이 이용할 수 있는 빌트인 계산 이 없다는 것을 말할 수 있습니다 . 그들은 다른 모든 사람들과 동일한 SSE 지침을 사용합니다. 두 번째 의견에 대해 상대적인 속도 fdiv는 중요하지 않습니다. 어떤 일을하는 두 가지 방법이 있고 하나가 다른 것보다 두 배 빠른 경우, 완전히 관련이없는 작업에 비해 얼마나 오래 걸리는지에 관계없이 느린 것을 "빠름"이라고 부르는 것은 이치에 맞지 않습니다.
Stephen Canon

1
sin라이브러리 의 소프트웨어 기능은 완전한 배정 밀도 정확도를 제공합니다. fsincos명령은 다소 정확도 (이중 확장) 제공하지만, 그 여분의 정확도가 떨어져 전화 대부분의 프로그램에서 발생됩니다 sin그 결과는 일반적으로 나중에 산술 연산 또는 메모리에 저장하여 배정 밀도로 반올림 한, 기능. 대부분의 상황에서 실제 사용을 위해 동일한 정확도를 제공합니다.
Stephen Canon

4
이 또한주의 fsincos그 자체로 완벽하게 구현되지 않습니다; 인수를 fsincos명령어 의 유효한 입력 범위에 넣으려면 추가 범위 축소 단계가 필요합니다 . 라이브러리 sincos함수에는이 감소와 핵심 계산이 포함되어 있으므로 내가 나열한주기 타이밍보다 훨씬 빠릅니다 (비교에 따라).
Stephen Canon

39

최신 x86 프로세서에는 사용자가 요청한 것을 정확히 수행하는 fsincos 명령어가 있습니다. sin과 cos를 동시에 계산합니다. 좋은 최적화 컴파일러는 같은 값에 대해 sin과 cos를 계산하는 코드를 감지하고이를 실행하기 위해 fsincos 명령을 사용해야합니다.

이것이 작동하려면 컴파일러 플래그를 약간 돌리는 것이 필요했지만 :

$ gcc --version
i686-apple-darwin9-gcc-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5488)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ cat main.c
#include <math.h> 

struct Sin_cos {double sin; double cos;};

struct Sin_cos fsincos(double val) {
  struct Sin_cos r;
  r.sin = sin(val);
  r.cos = cos(val);
  return r;
}

$ gcc -c -S -O3 -ffast-math -mfpmath=387 main.c -o main.s

$ cat main.s
    .text
    .align 4,0x90
.globl _fsincos
_fsincos:
    pushl   %ebp
    movl    %esp, %ebp
    fldl    12(%ebp)
    fsincos
    movl    8(%ebp), %eax
    fstpl   8(%eax)
    fstpl   (%eax)
    leave
    ret $4
    .subsections_via_symbols

Tada, fsincos 명령어를 사용합니다!


이것은 멋지다! -mfpmath = 387이 무엇을하는지 설명해 주시겠습니까? 그리고 MSVC에서도 작동합니까?
Danvil

1
참고 -ffast-math-mfpmath리드 경우에 따라 다른 결과이다.
Debilski 2010

3
mfpmath = 387은 gcc가 SSE 명령어 대신 x87 명령어를 사용하도록 강제합니다. 나는 MSVC에 유사한 최적화와 플래그가 있다고 생각하지만 MSVC가 확실하지 않습니다. x87 명령을 사용하면 다른 코드의 성능이 저하 될 수 있지만 인텔의 MKL을 사용하려면 다른 답변도 살펴 봐야합니다.
Chi

cygwin의 오래된 gcc 3.4.4는 fsinfcos. :-(
Vlad

가장 높은 최적화가 활성화 된 Visual Studio 2008로 시도했습니다. 2 개의 라이브러리 함수 __CIsin__CIcos.
Vlad

13

성능이 필요할 때 미리 계산 된 sin / cos 테이블을 사용할 수 있습니다 (하나의 테이블이 가능하며 사전으로 저장 됨). 글쎄, 그것은 당신이 필요로하는 정확도에 달려 있지만 (아마도 테이블이 클 것입니다), 정말 빨라야합니다.


그런 다음 입력 값을 [0,2 * pi] (또는 추가 검사를 통해 더 작게)에 매핑해야하며 fmod에 대한이 호출은 성능을 저하시킵니다. 내 (적절하게 차선책) 구현에서는 조회 테이블로 성능을 얻을 수 없었습니다. 여기에 조언이 있습니까?
Danvil

11
미리 계산 된 테이블이 sin캐시를 폐기하기 때문에 미리 계산 된 테이블은 호출하는 것보다 거의 확실히 느립니다 .
Andreas Brinck 2010

1
테이블의 크기에 따라 다릅니다. 256 개 항목 테이블은 종종 충분히 정확하고 1Kb 만 사용합니다. 많이 사용하면 나머지 앱 성능에 악영향을주지 않고 캐시에 갇히지 않을까요?
Mr. Boy

@Danvil : 여기 사인 룩업 테이블 en.wikipedia.org/wiki/Lookup_table#Computing_sines 의 예가 있습니다. 그러나 입력을 이미 [0; 2pi]에 매핑했다고 가정합니다.
tanascius

@AndreasBrinck 나는 그렇게 멀리 가지 않을 것입니다. (TM)에 따라 다릅니다. 최신 캐시는 거대하고 조회 테이블은 작습니다. 메모리 레이아웃에 약간의주의를 기울이면 룩업 테이블이 나머지 계산의 캐시 사용률에 어떤 차이도 만들 필요가 없습니다. 룩업 테이블이 캐시 안에 들어간다는 사실은 그것이 매우 빠른 이유 중 하나입니다. mem 레이아웃을 정확하게 제어하기 어려운 Java에서도 룩업 테이블로 엄청난 성능을 얻었습니다.
재로드 스미스

13

기술적으로는 복소수와 오일러 공식 을 사용하여이를 달성 할 수 있습니다. 따라서 (C ++)

complex<double> res = exp(complex<double>(0, x));
// or equivalent
complex<double> res = polar<double>(1, x);
double sin_x = res.imag();
double cos_x = res.real();

한 단계에서 사인과 코사인을 제공해야합니다. 이것이 내부적으로 어떻게 수행되는지는 사용되는 컴파일러와 라이브러리의 문제입니다. (오일러의 공식은 대부분 복잡한 계산하는 데 사용됩니다 단지 때문에 (그리고 힘) 잘이 방법을 수행하는 데 시간이 더 걸릴 수 있습니다 exp사용 sin하고 cos있지만, 가능한 이론적 최적화가있을 수 있습니다 - 다른 방법 빙글되지 않음).


편집하다

<complex>GNU C ++ 4.2 의 헤더 는 sincosinside 에 대한 명시 적 계산을 사용 polar하므로 컴파일러가 마법을 수행하지 않는 한 최적화에 너무 좋지 않습니다 ( Chi의 답변에 작성된 -ffast-math-mfpmath스위치 참조 ).


죄송합니다. 오일러의 공식은 실제로 무언가를 계산 하는 방법 을 알려주지 않습니다. 복잡한 지수를 실제 삼각 함수와 연결하는 신원 (매우 유용하지만) 일뿐입니다. 사인과 코사인을 함께 계산하면 이점이 있지만 공통 하위 표현식이 포함되며 귀하의 대답은 이에 대해 논의하지 않습니다.
Jason S

12

둘 중 하나를 계산 한 다음 ID를 사용할 수 있습니다.

cos (x) 2 = 1-sin (x) 2

그러나 @tanascius가 말했듯이 미리 계산 된 테이블이 갈 길입니다.


8
그리고이 방법을 사용하려면 거듭 제곱과 제곱근을 계산해야하므로 성능이 중요한 경우 다른 삼각 함수를 직접 계산하는 것보다 실제로 더 빠른지 확인해야합니다.
Tyler McHenry

4
sqrt()하드웨어에서 최적화되는 경우가 많으므로 sin()또는 cos(). 힘은 자기 곱이기 때문에 pow(). 하드웨어 지원없이 매우 빠르게 합리적으로 정확한 제곱근을 얻을 수있는 몇 가지 트릭이 있습니다. 마지막으로이 작업을 수행하기 전에 프로필을 작성해야합니다.
deft_code 2010

12
√ (1-cos ^ 2 x)는 sin x를 직접 계산하는 것보다 덜 정확합니다. 특히 x ~ 0
그렇습니다.

1
작은 x의 경우 y = sqrt (1-x * x)에 대한 Taylor 급수가 매우 좋습니다. 처음 3 개 항으로 좋은 정확도를 얻을 수 있으며 몇 번의 곱셈과 한 번의 교대 만 필요합니다. 고정 소수점 코드에서 사용했습니다.
phkahler 2010

1
@phkahler : Taylor 시리즈는 적용되지 않습니다. x ~ 0, cos x ~ 1 일 때
kennytm

10

GNU C 라이브러리를 사용하는 경우 다음을 수행 할 수 있습니다.

#define _GNU_SOURCE
#include <math.h>

sincos(), sincosf()sincosl()두 값을 함께 계산하는 함수의 선언을 얻을 수 있습니다. 아마도 대상 아키텍처에 대해 가장 빠른 방법 일 것입니다.


8

이 포럼 페이지에는 빠른 근사치를 찾는 데 초점을 맞춘 매우 흥미로운 내용이 있습니다. http://www.devmaster.net/forums/showthread.php?t=5784

면책 조항 :이 물건을 직접 사용하지 않았습니다.

2018 년 2 월 22 일 업데이트 : Wayback Machine은 현재 원본 페이지를 방문하는 유일한 방법입니다 : https://web.archive.org/web/20130927121234/http://devmaster.net/posts/9648/fast-and-accurate- 사인 코사인


나는 이것도 시도했고 꽤 좋은 성능을 주었다. 그러나 sin과 cos는 독립적으로 계산됩니다.
Danvil

내 느낌은이 사인 / 코사인 계산이 사인을 얻고 제곱근 근사를 사용하여 코사인을 얻는 것보다 빠르지 만 테스트를 통해 확인할 수 있습니다. 사인과 코사인의 주요 관계는 위상 중 하나입니다. 이것을 고려하여 위상 편이 코사인 호출에 대해 계산 한 사인 값을 재사용 할 수 있도록 코딩 할 수 있습니까? (이것은 스트레칭 일 수 있지만 요청해야했습니다)
Joel Goodwin

직접적으로는 아닙니다 (정확히 묻는 질문에도 불구하고). 나는 죄와 값 x의 cos가 필요하고 다른 곳에서 우연히 x + pi / 2를 계산했는지 알 수있는 방법이 없습니다 ...
Danvil

내 게임에서 입자 원을 그리는 데 사용했습니다. 시각적 효과 일 뿐이므로 결과는 충분히 가깝고 성능이 정말 인상적입니다.
Maxim Kamalov

나는 인상적이지 않다. 체비 쇼프 근사는 일반적으로 주어진 성능에 대해 가장 높은 정확도를 제공합니다.
Jason S

7

caf에서 알 수 있듯이 많은 C 수학 라이브러리에는 이미 sincos ()가 있습니다. 주목할만한 예외는 MSVC입니다.

  • Sun은 최소한 1987 년부터 sincos ()를 사용했습니다 (23 년, 하드 카피 매뉴얼 페이지가 있습니다).
  • HPUX 11은 1997 년에 사용했습니다 (그러나 HPUX 10.20에는 없음)
  • 버전 2.1에서 glibc에 추가됨 (1999 년 2 월)
  • gcc 3.4 (2004), __builtin_sincos ()에서 내장되었습니다.

그리고 조회와 관련하여 Art of Unix Programming (2004) (Chapter 12)의 Eric S. Raymond는 다음 같이 명시 적으로 잘못된 생각이라고 말합니다 (현재 시점에서) :

"또 다른 예는 작은 테이블을 미리 계산하는 것입니다. 예를 들어 3D 그래픽 엔진에서 회전을 최적화하기위한 sin (x) 테이블은 최신 컴퓨터에서 365 × 4 바이트를 차지합니다. 프로세서가 캐싱을 요구하기에 메모리보다 충분히 빨라지기 전에 , 이것은 명백한 속도 최적화였습니다. 요즘에는 테이블로 인해 발생하는 추가 캐시 미스 비율을 지불하는 것보다 매번 재 계산하는 것이 더 빠를 수 있습니다.

"하지만 미래에는 캐시가 커짐에 따라 다시 돌아올 수 있습니다.보다 일반적으로 많은 최적화는 일시적이며 비용 비율이 변함에 따라 쉽게 비관적으로 변할 수 있습니다. 알 수있는 유일한 방법은 측정하고 보는 것입니다." ( Art of Unix Programming에서 )

그러나 위의 논의에서 볼 때 모든 사람이 동의하는 것은 아닙니다.


10
"365 x 4 바이트". 윤년을 고려해야하므로 실제로는 365.25 x 4 바이트가되어야합니다. 또는 그는 지구의 연도의 일수 대신 원의 도수를 사용하려고했을 수도 있습니다.
Ponkadoodle

@Wallacoloo : 좋은 관찰입니다. 나는 그것을 놓쳤다. 그러나 오류는 원본에 있습니다.
Joseph Quinsey

LOL. 또한 그는 해당 분야의 많은 컴퓨터 게임에서 제한된 수의 각도 만 필요 하다는 사실무시합니다 . 가능한 각도를 안다면 캐시 미스가 없습니다. 이 경우에는 테이블을 정확하게 사용 fsincos하고 다른 사용자에게는 (CPU 명령!) 시도해 보겠습니다. 종종 큰 테이블에서 sin과 cos를 보간하는 것만 큼 빠릅니다.
Erich Schubert 2013 년

5

나는 조회 테이블이 반드시이 문제에 대해 좋은 생각이라고 생각하지 않습니다. 정확도 요구 사항이 매우 낮지 않은 한 테이블은 매우 커야합니다. 그리고 최신 CPU는 주 메모리에서 값을 가져 오는 동안 많은 계산을 수행 할 수 있습니다. 이것은 논쟁으로 적절하게 대답 할 수있는 질문 중 하나가 아닙니다 (저것도 아닙니다). 데이터를 테스트하고 측정하고 고려합니다.

그러나 AMD의 ACML 및 Intel의 MKL과 같은 라이브러리에서 찾을 수있는 SinCos의 빠른 구현을 살펴 보겠습니다.


3

상용 제품을 기꺼이 사용하고 동시에 많은 sin / cos 계산을 계산하는 경우 (벡터 함수를 사용할 수 있음) 인텔의 수학 커널 라이브러리를 확인해야합니다 .

그것은이 sincos 기능을

해당 문서에 따르면 고정밀 모드의 코어 2 듀오에서 평균 13.08 클럭 / 요소이며, fsincos보다 훨씬 빠를 것이라고 생각합니다.


1
마찬가지로 OSX에서는 Accelerate.framework를 사용 vvsincos하거나 사용할 수 있습니다 vvsincosf. AMD는 벡터 라이브러리에서도 유사한 기능을 가지고 있다고 생각합니다.
Stephen Canon


2

이런 종류의 일에 성능이 중요 할 때 조회 테이블을 도입하는 것은 드문 일이 아닙니다.


2

창의적인 접근 방식을 위해 Taylor 시리즈를 확장하는 것은 어떻습니까? 유사한 용어가 있으므로 다음 의사와 같이 할 수 있습니다.

numerator = x
denominator = 1
sine = x
cosine = 1
op = -1
fact = 1

while (not enough precision) {
    fact++
    denominator *= fact
    numerator *= x

    cosine += op * numerator / denominator

    fact++
    denominator *= fact
    numerator *= x

    sine += op * numerator / denominator

    op *= -1
}

이것은 다음과 같은 것을 의미합니다 : sin과 cosine에 대해 x와 1에서 시작하여 패턴을 따르십시오-x ^ 2 / 2를 빼십시오! 코사인에서 x ^ 3 / 3을 빼세요! 사인에서 x ^ 4 / 4를 더하세요! 코사인에 x ^ 5 / 5를 더하세요! 사인을 ...

이것이 성능이 될지 모르겠습니다. 내장 된 sin () 및 cos ()가 제공하는 것보다 정밀도가 낮다면 옵션이 될 수 있습니다.


실제로 i- 사인 확장 계수는 i- 코사인 확장 계수의 x / i 배입니다. 하지만 Taylor 시리즈를 사용하는 것이 정말 빠르다는 것은 의심 스럽습니다.
Danvil

1
Chebyshev는 다항 함수 근사에 대해 Taylor보다 훨씬 낫습니다. Taylor 근사를 사용하지 마십시오.
Timmmm

여기에는 숫자로 된 가짜가 많이 있습니다. 분자와 분모 모두 빠르게 커져서 부동 소수점 오류가 발생합니다. "정밀도가 충분하지 않음"을 어떻게 결정하고 계산하는 방법은 말할 것도 없습니까? 테일러 근사는 단일 지점 주변의 이웃에서 좋습니다. 그 지점에서 벗어나면 빠르게 부정확 해지고 많은 항이 필요하기 때문에 Timmmm의 Chebyshev 근사 (주어진 간격에 대해 좋은 근사치를 생성 함)에 대한 제안이 좋은 이유입니다.
Jason S

2

CEPHES 라이브러리에는 매우 빠를 수있는 멋진 솔루션이 있으며 약간 더 / 더 적은 CPU 시간 동안 매우 유연하게 정확도를 추가 / 제거 할 수 있습니다.

cos (x)와 sin (x)는 exp (ix)의 실수 부와 허수 부임을 기억하십시오. 그래서 우리는 둘 다 얻기 위해 exp (ix)를 계산하려고합니다. 0과 2pi 사이의 y의 일부 이산 값에 대해 exp (iy)를 미리 계산합니다. x를 간격 [0, 2pi)로 이동합니다. 그런 다음 x에 가장 가까운 y를 선택하고
exp (ix) = exp (iy + (ix-iy)) = exp (iy) exp (i (xy))를 씁니다 .

우리는 조회 테이블에서 exp (iy)를 얻습니다. 그리고 | xy | 작고 (y- 값 사이의 거리의 절반 정도) Taylor 시리즈는 몇 가지 용어로 멋지게 수렴하므로 exp (i (xy))에 사용합니다. 그리고 exp (ix)를 얻기 위해 복잡한 곱셈이 필요합니다.

이것의 또 다른 장점은 SSE를 사용하여 벡터화 할 수 있다는 것입니다.


2

당신은 한 번 봐 가지고 할 수 있습니다 http://gruntthepeon.free.fr/ssemath/ CEPHES 라이브러리에서 영감을 SSE 벡터화 구현을 제공합니다. 그것은 좋은 정확도 (5e-8 정도의 sin / cos로부터의 최대 편차)와 속도 (단일 호출 기준으로 fsincos보다 약간 우월하고 여러 값에서 확실한 승자)를 가지고 있습니다.




0

두 함수에 대한 조회 테이블을 선언 할 생각이 있습니까? 여전히 sin (x) 및 cos (x)를 "계산"해야하지만 높은 정확도가 필요하지 않으면 확실히 더 빠를 것입니다.


0

MSVC 컴파일러는 (내부) SSE2 함수를 사용할 수 있습니다.

 ___libm_sse2_sincos_ (for x86)
 __libm_sse2_sincos_  (for x64)

적절한 컴파일러 플래그가 지정된 경우 최적화 된 빌드에서 (최소 / O2 / arch : SSE2 / fp : fast). 이러한 함수의 이름은 별도의 sin과 cos를 계산하지 않고 "한 단계로"계산한다는 것을 의미하는 것 같습니다.

예를 들면 :

void sincos(double const x, double & s, double & c)
{
  s = std::sin(x);
  c = std::cos(x);
}

/ fp : fast를 사용한 어셈블리 (x86 용) :

movsd   xmm0, QWORD PTR _x$[esp-4]
call    ___libm_sse2_sincos_
mov     eax, DWORD PTR _s$[esp-4]
movsd   QWORD PTR [eax], xmm0
mov     eax, DWORD PTR _c$[esp-4]
shufpd  xmm0, xmm0, 1
movsd   QWORD PTR [eax], xmm0
ret     0

/ fp : fast가 없지만 대신 / fp : precise (기본값)를 사용하는 어셈블리 (x86 용)는 별도의 sin 및 cos를 호출합니다.

movsd   xmm0, QWORD PTR _x$[esp-4]
call    __libm_sse2_sin_precise
mov     eax, DWORD PTR _s$[esp-4]
movsd   QWORD PTR [eax], xmm0
movsd   xmm0, QWORD PTR _x$[esp-4]
call    __libm_sse2_cos_precise
mov     eax, DWORD PTR _c$[esp-4]
movsd   QWORD PTR [eax], xmm0
ret     0

따라서 / fp : fast는 sincos 최적화에 필수입니다.

그러나

___libm_sse2_sincos_

아마 정확하지 않을 수 있습니다

__libm_sse2_sin_precise
__libm_sse2_cos_precise

이름 끝에 "정확한"이 누락 되었기 때문입니다.

최신 MSVC 2019 컴파일러와 적절한 최적화를 사용하는 "약간"이전 시스템 (Intel Core 2 Duo E6750)에서 내 벤치 마크에 따르면 sincos 호출이 개별 sin 및 cos 호출보다 약 2.4 배 빠릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.