पाप और कॉस की एक साथ गणना करने का सबसे तेज़ तरीका क्या है?


100

मैं एक मूल्य के साइन और सह-साइन दोनों को एक साथ गणना करना चाहता हूं (उदाहरण के लिए एक रोटेशन मैट्रिक्स बनाने के लिए)। बेशक, मैं उन्हें एक के बाद एक अलग-अलग तरह से गणना कर सकता था a = cos(x); b = sin(x);, लेकिन मुझे आश्चर्य है कि क्या दोनों मूल्यों की आवश्यकता होने पर एक तेज़ तरीका है।

संपादित करें: अब तक के उत्तरों को संक्षेप में प्रस्तुत करने के लिए:

  • व्लाद ने कहा, किFSINCOSदोनों के लिए एक हीकमांडकंप्यूटिंग है (लगभग एक ही समय मेंFSINअकेलेकॉल करने के लिए)

  • जैसा कि ची ने देखा, यह अनुकूलन कभी-कभी कंपाइलर द्वारा किया जाता है (अनुकूलन झंडे का उपयोग करते समय)।

  • कैफे ने बताया, यह कार्यsincosऔरsincosfशायद उपलब्ध हैं और सीधे शामिल करके ही बुलाया जा सकता हैmath.h

  • एक नज़र तालिका का उपयोग करने के tanascius दृष्टिकोण विवादास्पद है। (हालांकि मेरे कंप्यूटर पर और एक बेंचमार्क परिदृश्य में यहsincos32-बिट फ़्लोटिंग पॉइंट के लिए लगभग एक ही सटीकता के साथ3 गुना तेज़ी से चलता है)।

  • जोएल गुडविन काफी अच्छे सटीक (मेरे लिए, यह और भी तेज है तो टेबल लुक-अप) के साथ एक चरम तेजी से सन्निकटन तकनीक के एक दिलचस्प दृष्टिकोण से जुड़ा हुआ है।


1
इस सवाल को पाप / कॉस के मूल कार्यान्वयन के बारे में भी देखें: stackoverflow.com/questions/1640595
जोएल गुडविन

1
कोशिश sinx ~ x-x^3/6और cosx~1-x^2/4अनुमानों के रूप में आप सटीकता की तुलना में अधिक गति के बारे में परवाह है। आप सटीकता पर और अधिक भार डालते हुए या तो श्रृंखला में शब्दों को जोड़ सकते हैं ( en.wikipedia.org/wiki/Taylor_series taylor श्रृंखला को चालू करने के लिए नीचे स्क्रॉल करें।) ध्यान दें कि यह किसी भी फ़ंक्शन को अनुमानित करने का एक सामान्य तरीका है जिसे आप अलग-अलग समय पर चाहते हैं n। इसलिए यदि आपके पास कुछ बड़ा कार्य है जो कि साइन और कोजाइन का है तो आपको एक बहुत बड़ी गति मिलेगी यदि आप इसे पाप के बजाय अनुमानित करते हैं, तो कॉस स्वतंत्र रूप से।
ldog

यह बहुत खराब सटीकता के साथ खराब तकनीक है। जोएल गुडविन द्वारा पोस्ट देखें। टेलर श्रृंखला नीचे पोस्ट की गई है। कृपया इसे उत्तर के रूप में पोस्ट करें।
डेनविल

1
वैसे यह आपकी आवश्यकताओं पर निर्भर करता है, यदि आप सटीकता चाहते हैं टेलर श्रृंखला केवल एक अच्छा सन्निकटन होगा यदि आपको xकिसी बिंदु के करीब मूल्यों की आवश्यकता है x_0, तो x_00. के बजाय अपनी टेलर श्रृंखला का विस्तार करें । यह आपको उत्कृष्ट सटीकता प्रदान करेगा x_0लेकिन निकटवर्ती खराब परिणाम जाओ। आपने शायद सोचा कि सटीकता बेकार हो जाती है क्योंकि आपने दिए गए asnwer को देखा और इसे मूल्यों से दूर करने की कोशिश की 0। यह जवाब पाप के साथ है, क्योंकि कॉस का विस्तार लगभग 0.
ldog

जवाबों:


52

आधुनिक इंटेल / एएमडी प्रोसेसर में 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

आशा है कि उनमें से एक मदद करता है। (मैंने खुद इस निर्देश का उपयोग नहीं किया, क्षमा करें।)

जैसा कि वे प्रोसेसर स्तर पर समर्थित हैं, मुझे उम्मीद है कि वे टेबल लुकअप की तुलना में बहुत तेज़ होंगे।

संपादित करें:
विकिपीडिया सुझाव देता है कि FSINCOS387 प्रोसेसर में जोड़ा गया था, इसलिए आप शायद ही ऐसा प्रोसेसर पा सकते हैं जो इसका समर्थन नहीं करता है।

संपादित करें:
इंटेल के प्रलेखन में कहा गया है कि (यानी फ्लोटिंग पॉइंट डिवीजन) FSINCOSकी तुलना में लगभग 5 गुना धीमा है FDIV

संपादित करें:
कृपया ध्यान दें कि सभी आधुनिक संकलक एक कॉल में साइन और कोज़ाइन की गणना का अनुकूलन नहीं करते हैं FSINCOS। विशेष रूप से, मेरे वीएस 2008 ने ऐसा नहीं किया।

संपादित करें:
पहला उदाहरण लिंक मृत है, लेकिन वेबैक मशीन में अभी भी एक संस्करण है


1
@ इफाह्लर: यह बहुत अच्छा होगा। पता नहीं कि इस तरह के अनुकूलन का उपयोग आधुनिक संकलक द्वारा किया जाता है या नहीं।
व्लाद

12
fsincosअनुदेश है नहीं "काफी तेजी से"। इंटेल के स्वयं के अनुकूलन मैनुअल ने हाल ही में माइक्रो-आर्किटेक्चर पर 119 और 250 चक्रों के बीच इसकी आवश्यकता के रूप में उद्धरण दिया। इंटेल के गणित पुस्तकालय (आईसीसी के साथ वितरित), तुलना करके, अलग से गणना कर सकते हैं sinऔर cos100 से भी कम चक्रों में, एक सॉफ्टवेयर कार्यान्वयन का उपयोग कर सकते हैं जो x87 इकाई के बजाय SSE का उपयोग करता है। एक समान सॉफ्टवेयर कार्यान्वयन जो एक साथ दोनों की गणना करता है वह अभी भी तेज हो सकता है।
स्टीफन कैनन

2
@ वीएलडी: आईसीसी गणित पुस्तकालय खुले स्रोत नहीं हैं, और मेरे पास उन्हें पुनर्वितरित करने का लाइसेंस नहीं है, इसलिए मैं विधानसभा को पोस्ट नहीं कर सकता। मैं आपको बता सकता हूं कि sinउनके लिए लाभ उठाने के लिए कोई अंतर्निहित संगणना नहीं है, हालांकि; वे सभी के समान SSE निर्देशों का उपयोग करते हैं। आपकी दूसरी टिप्पणी के लिए, गति के सापेक्ष fdivगतिहीन है; अगर कुछ करने के दो तरीके हैं और एक दूसरे की तुलना में दोगुना है, तो धीमे से एक "तेज" कहने का कोई मतलब नहीं है, भले ही यह पूरी तरह से असंबंधित कार्य के सापेक्ष कितना लंबा हो।
स्टीफन कैनन

1
sinउनकी लाइब्रेरी में सॉफ़्टवेयर फ़ंक्शन पूर्ण डबल-सटीक सटीकता प्रदान करता है। fsincosअनुदेश कुछ और अधिक सटीकता (डबल विस्तारित) बचाता है, लेकिन यह है कि अतिरिक्त सटीकता ज्यादातर कार्यक्रमों फोन है कि में दूर फेंक दिया जाता है sin, समारोह के रूप में उसके परिणाम आमतौर पर बाद में अंकगणितीय आपरेशनों या स्मृति के लिए एक दुकान से डबल परिशुद्धता के लिए गोल है। ज्यादातर स्थितियों में, वे व्यावहारिक उपयोग के लिए समान सटीकता प्रदान करते हैं।
स्टीफन कैनन

4
ध्यान दें कि fsincosयह अपने आप में पूर्ण कार्यान्वयन नहीं है; fsincosअनुदेश के लिए मान्य इनपुट श्रेणी में तर्क को रखने के लिए आपको एक अतिरिक्त रेंज रिडक्शन स्टेप की आवश्यकता होती है । लाइब्रेरी sinऔर cosफ़ंक्शंस में इस कमी के साथ-साथ कोर कम्प्यूटेशन भी शामिल है, इसलिए वे मेरे द्वारा सूचीबद्ध किए गए चक्र समय की तुलना में और भी तेज़ (तुलना करके) हैं।
स्टीफन कैनन

39

आधुनिक x86 प्रोसेसर में एक fincincos निर्देश होता है, जो आपसे वही पूछ रहा है - जो एक ही समय में पाप और 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

टाडा, यह fsincos निर्देश का उपयोग करता है!


यह अच्छा है! क्या आप बता सकते हैं कि -mfpmath = 387 क्या कर रहा है? और क्या यह MSVC के साथ भी काम करता है?
दानविल

1
ध्यान दें कि -ffast-mathऔर -mfpmathकुछ मामलों में विभिन्न परिणामों के लिए नेतृत्व।
डेबिल्स्की

3
mfpmath = 387 SSE निर्देशों के बजाय g87 को x87 निर्देशों का उपयोग करने के लिए मजबूर करेगा। मुझे संदेह है कि MSVC में समान अनुकूलन और झंडे हैं, लेकिन मेरे पास सुनिश्चित करने के लिए MSVC काम नहीं है। X87 निर्देशों का उपयोग करने से संभवतः अन्य कोड में प्रदर्शन के लिए एक बाधा होगी, हालांकि, आपको Intel के MKL का उपयोग करने के लिए मेरे अन्य उत्तर को भी देखना चाहिए।
ची

मेरे पुराने gcc 3.4.4 से cygwin में fsinऔर के लिए 2 अलग-अलग कॉल का उत्पादन होता है fcos। :-(
व्लाद

विजुअल स्टूडियो 2008 के साथ उच्चतम अनुकूलन सक्षम करने की कोशिश की। यह 2 पुस्तकालय कार्यों __CIsinऔर बुलाता है __CIcos
व्लाद

13

जब आपको प्रदर्शन की आवश्यकता होती है, तो आप एक पूर्वगामी पाप / कॉस टेबल (एक तालिका, एक शब्दकोश के रूप में संग्रहीत) का उपयोग कर सकते हैं। ठीक है, यह आपकी ज़रूरत की सटीकता पर निर्भर करता है (हो सकता है कि मेज बड़ी होगी), लेकिन यह वास्तव में तेज़ होना चाहिए।


फिर इनपुट वैल्यू को मैप किया जाना चाहिए [0,2 * pi] (या अतिरिक्त जांच के साथ छोटा) और यह कॉल fmod दूर प्रदर्शन को खाती है। मेरे (यथोचित सबॉप्टीमल) कार्यान्वयन में मैं लुक-अप टेबल के साथ प्रदर्शन हासिल नहीं कर सका। क्या आपकी यहाँ कोई सलाह होगी?
दानविल

11
एक precomputed तालिका लगभग निश्चित रूप से सिर्फ बुला से धीमी sinहोगी क्योंकि precomputed तालिका कैश कचरा कर देगा।
एंड्रियास ब्रिनक

1
यह निर्भर करता है कि मेज कितनी बड़ी है। एक 256-प्रविष्टि तालिका अक्सर काफी सटीक होती है और केवल 1Kb का उपयोग करती है ... यदि आप इसका उपयोग करते हैं तो यह ऐप के बाकी प्रदर्शन को प्रतिकूल रूप से प्रभावित किए बिना कैश में फंस नहीं जाएगा?
मिस्टर बॉय

@Danvil: यहां साइन लुकिंग टेबल en.wikipedia.org/wiki/Lookup_table#Computing_sines का उदाहरण दिया गया है । हालाँकि यह मानता है कि आपने पहले ही अपने इनपुट को [0; 2pi] में मैप कर दिया है।
tanascius

@AndreasBrinck मैं इतनी दूर नहीं जाऊँगा। यह निर्भर करता है (TM)। आधुनिक कैश विशाल हैं और लुकअप टेबल छोटे हैं। अक्सर अगर आप मेमोरी लेआउट में थोड़ा ध्यान रखते हैं तो आपके लुकअप टेबल को आपके बाकी कंपीटिशन के कैशे के उपयोग से कोई फर्क नहीं पड़ता है। तथ्य यह है कि लुकअप टेबल कैश के अंदर फिट बैठता है एक कारण है कि यह बहुत तेज़ है। जावा में भी जहां मेम लेआउट को ठीक से नियंत्रित करना मुश्किल है, मैंने लुकअप तालिकाओं के साथ बड़े पैमाने पर प्रदर्शन जीत लिया है।
जारोड स्मिथ

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 के लिए शीर्षलेख अंदर sinऔर cosअंदर की स्पष्ट गणनाओं का उपयोग कर रहे हैं polar, इसलिए यह वहां अनुकूलन के लिए बहुत अच्छा नहीं लगता है जब तक कि कंपाइलर कुछ जादू नहीं करता (देखें -ffast-mathऔर ची के उत्तर-mfpmath में लिखे अनुसार स्विच करता है )।


क्षमा करें, लेकिन यूलर का फॉर्मूला वास्तव में आपको कुछ गणना करने का तरीका नहीं बताता है, यह सिर्फ एक पहचान है (यद्यपि यह बहुत उपयोगी है) जो वास्तविक त्रिकोणमितीय कार्यों में जटिल घातांक से संबंधित है। साइन और कोसाइन की गणना के लाभ एक साथ हैं, लेकिन उनमें आम सबटेक्शंस शामिल हैं और आपका जवाब इस पर चर्चा नहीं करता है।
जेसन एस

12

आप या तो गणना कर सकते हैं और फिर पहचान का उपयोग कर सकते हैं:

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

लेकिन जैसा कि @tanascius कहते हैं, एक पूर्वनिर्मित टेबल जाने का रास्ता है।


8
और ध्यान रखें कि इस पद्धति का उपयोग करने पर एक शक्ति और एक वर्गमूल की गणना होती है, इसलिए यदि प्रदर्शन महत्वपूर्ण है, तो यह सुनिश्चित करना सुनिश्चित करें कि यह वास्तव में दूसरे ट्रिगर फ़ंक्शन की गणना करने से सीधे तेज है।
टायलर मैकहेनरी

4
sqrt()अक्सर हार्डवेयर में अनुकूलित किया जाता है, इसलिए यह बहुत अच्छी तरह से तेज हो सकता है sin()या cos()। शक्ति सिर्फ आत्म गुणन है, इसलिए उपयोग न करें pow()। हार्डवेयर समर्थन के बिना बहुत जल्दी वर्ग-मूल प्राप्त करने के लिए कुछ तरकीबें हैं। अंत में, इनमें से कोई भी करने से पहले प्रोफाइल ज़रूर करें।
deft_code

12
ध्यान दें कि is (1 - cos ^ 2 x) सीधे पाप x की गणना करने से कम सटीक है, विशेष रूप से जब x ~ 0.
kennytm

1
छोटे x के लिए, y = sqrt (1-x * x) के लिए टेलर श्रृंखला बहुत अच्छी है। आप पहले 3 शब्दों के साथ अच्छी सटीकता प्राप्त कर सकते हैं और इसके लिए केवल कुछ गुणा और एक शिफ्ट की आवश्यकता होती है। मैंने इसे निश्चित बिंदु कोड में उपयोग किया है।
फकहलर

1
@ फकहलर: आपकी टेलर सीरीज़ लागू नहीं होती है क्योंकि जब 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

डिस्क्लेमर: इस सामान का कोई भी इस्तेमाल खुद नहीं करता।

अपडेट 22 फरवरी 2018: वेकबैक मशीन अब मूल पृष्ठ पर जाने का एकमात्र तरीका है: https://web.archive.org/web/20130927121234/http://devmaster.net/posts/9648/and-accurate- साइन-कोज्या


मैंने इसे भी आजमाया, और इसने मुझे काफी अच्छा प्रदर्शन दिया। लेकिन पाप और कॉस की गणना स्वतंत्र रूप से की जाती है।
दानविल

मेरी भावना है कि यह साइन / कोसाइन गणना साइन प्राप्त करने और कोसाइन प्राप्त करने के लिए एक वर्गमूल सन्निकटन का उपयोग करने से तेज होगा, लेकिन एक परीक्षण यह सत्यापित करेगा। साइन और कोसाइन के बीच प्राथमिक संबंध चरण में से एक है; क्या यह संभव है कि आप अपने खाते में चरण-स्थानांतरित कोसाइन कॉल के लिए गणना करने वाले साइन मूल्यों का फिर से उपयोग कर सकें? (यह एक खिंचाव हो सकता है, लेकिन पूछना पड़ा)
जोएल गुडविन

सीधे तौर पर नहीं (प्रश्न के ठीक-ठीक पूछने के बावजूद)। मुझे एक मूल्य x के पाप और कॉशन की आवश्यकता है और यह जानने का कोई तरीका नहीं है कि क्या किसी अन्य स्थान पर मैं संयोग से x + pi / 2 ...
Danvil

मैंने अपने खेल में इसका इस्तेमाल कणों का एक घेरा बनाने के लिए किया। चूंकि यह सिर्फ एक दृश्य प्रभाव है, परिणाम काफी करीब है, और पूर्णता वास्तव में प्रभावशाली है।
मैक्सिम कमालोव

मैं प्रभावित नहीं हूँ; Chebyshev सन्निकटन आमतौर पर आपको दिए गए प्रदर्शन के लिए सबसे अधिक सटीकता प्रदान करते हैं।
जेसन एस

7

कई सी गणित पुस्तकालय, जैसा कि कैफे इंगित करता है, पहले से ही सिनकोस () है। उल्लेखनीय अपवाद MSVC है।

  • सन में कम से कम 1987 (तेईस वर्ष के बाद से ईमानदारी से) है, मेरे पास एक हार्ड-कॉपी मैन पेज है)
  • एचपीयूएक्स 11 में यह 1997 में था (लेकिन एचपीयूसी 10.20 में नहीं है)
  • संस्करण 2.1 में glibc को जोड़ा गया (फरवरी 1999)
  • बिल्ट-इन gcc 3.4 (2004), __builtin_sincos () बन गया।

और लुक-अप के बारे में, यूनिक्स की प्रोग्रामिंग में एरिक एस। रेमंड (2004) (अध्याय 12) स्पष्ट रूप से यह एक बुरा विचार (वर्तमान समय में) कहते हैं:

"एक अन्य उदाहरण छोटे तालिकाओं को प्री-कॉम्पटिशन कर रहा है - उदाहरण के लिए, एक 3 डी ग्राफिक्स इंजन में रोटेशन को अनुकूलित करने के लिए डिग्री द्वारा पाप की एक तालिका (x) एक आधुनिक मशीन पर 365 × 4 बाइट लेगी। प्रोसेसर से पहले कैशिंग की मांग करने के लिए मेमोरी की तुलना में काफी तेज हो गया। , यह एक स्पष्ट गति अनुकूलन था। आजकल तालिका के कारण अतिरिक्त कैश मिसेज़ के प्रतिशत के लिए भुगतान करने के बजाय प्रत्येक बार पुन: उपयोग करना तेज़ हो सकता है।

"लेकिन भविष्य में, यह फिर से बदल सकता है क्योंकि कैश बड़ा हो जाता है। आमतौर पर, कई अनुकूलन अस्थायी होते हैं और आसानी से निराशा में बदल सकते हैं क्योंकि लागत अनुपात में बदलाव होता है। जानने का एकमात्र तरीका उपाय और देखना है।" ( यूनिक्स प्रोग्रामिंग की कला से )

लेकिन, ऊपर चर्चा से देखते हुए, हर कोई सहमत नहीं है।


10
"365 x 4 बाइट्स"। आपको लीप वर्ष के लिए खाते की आवश्यकता है, ताकि वास्तव में 365.25 x 4 बाइट्स हो। या शायद वह पृथ्वी वर्ष में दिनों की संख्या के बजाय एक सर्कल में डिग्री की संख्या का उपयोग करने का मतलब था।
पोंकाडूडल

@Wallacoloo: अच्छा अवलोकन। मैनें इसे खो दिया। लेकिन त्रुटि मूल में है
जोसेफ क्विंसे

जबरदस्त हंसी। इसके अलावा, वह इस तथ्य की उपेक्षा करता है कि उस क्षेत्र के कई कंप्यूटर गेमों में, आपको केवल कोणों की एक सीमित संख्या की आवश्यकता होगी। कोई कैश मिस नहीं हैं, यदि आप संभावित कोणों को जानते हैं। मैं इस मामले में बिल्कुल तालिकाओं का उपयोग करूंगा, और fsincosदूसरों के लिए एक सीपीयू (सीपीयू निर्देश!) दें। यह अक्सर एक बड़ी मेज से पाप और कॉस को प्रक्षेपित करने जितना तेज़ होता है।
एरच Schubert

5

मैं नहीं मानता कि लुकअप टेबल इस समस्या के लिए एक अच्छा विचार है। जब तक आपकी सटीकता की आवश्यकताएं बहुत कम नहीं होती हैं तब तक तालिका को बहुत बड़ा होना चाहिए। और आधुनिक सीपीयू बहुत अधिक गणना कर सकते हैं जबकि मुख्य मेमोरी से एक मूल्य प्राप्त होता है। यह उन सवालों में से एक नहीं है, जो तर्क से ठीक से उत्तर दिया जा सकता है (मेरा भी नहीं), परीक्षण और माप और डेटा पर विचार करें।

लेकिन मैं सिनकोस के तेजी से कार्यान्वयन को देखता हूं जो आपको एएमडी के एसीएमएल और इंटेल के एमकेएल जैसे पुस्तकालयों में मिलते हैं।


3

यदि आप एक वाणिज्यिक उत्पाद का उपयोग करने के लिए तैयार हैं, और एक ही समय में कई पाप / कॉस की गणना कर रहे हैं (इसलिए आप vectored फ़ंक्शन का उपयोग कर सकते हैं), तो आपको Intel की गणित कर्नेल लाइब्रेरी की जांच करनी चाहिए

यह एक sincos फ़ंक्शन है

उस प्रलेखन के अनुसार, यह उच्च सटीकता मोड में कोर 2 जोड़ी पर 13.08 घड़ियों / तत्व का औसत है, जो मुझे लगता है कि fsincos से भी तेज होगा।


1
इसी तरह, OSX पर एक vvsincosया vvsincosfAccelerate.framework से उपयोग कर सकते हैं । मेरा मानना ​​है कि एएमडी के वेक्टर लाइब्रेरी में भी इसी तरह के कार्य होते हैं।
स्टीफन कैनन

3

यह लेख बताता है कि एक परवलयिक एल्गोरिथ्म का निर्माण कैसे किया जाता है जो साइन और कोसिन दोनों उत्पन्न करता है:

डीएसपी ट्रिक: पाप और कॉस का एक साथ परवलयिक स्वीकृति

http://www.dspguru.com/dsp/tricks/parabolic-approximation-of-sin-and-cos


1
हम्म् ... मुझे इस और चेबीशेव सन्निकटन के बीच एक शूटआउट करने की आवश्यकता है जो मुझे लगता है कि जीत होगी।
जेसन एस

2

जब प्रदर्शन इस तरह की चीज के लिए महत्वपूर्ण होता है तो लुकअप टेबल को पेश करना असामान्य नहीं होता है।


2

एक रचनात्मक दृष्टिकोण के लिए, टेलर श्रृंखला के विस्तार के बारे में कैसे? चूँकि उनके समान शब्द हैं, आप निम्न छद्म की तरह कुछ कर सकते हैं:

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
}

इसका मतलब है कि आप ऐसा कुछ करते हैं: पाप और कोसिन के लिए x और 1 से शुरू होकर, पैटर्न का पालन करें - x ^ 2/2 घटाएं! कोसाइन से, x ^ 3/3 घटाएँ! साइन से, x ^ 4/4 जोड़ें! कोसाइन करने के लिए, x ^ 5/5 जोड़ें! साइन करने के लिए ...

मुझे नहीं पता कि क्या यह प्रदर्शन होगा। यदि आपको पाप () और कॉस () में निर्मित की तुलना में कम सटीकता की आवश्यकता है, तो यह एक विकल्प हो सकता है।


वास्तव में i-sine एक्सटेंशन फैक्टर x / i है i-cosine एक्सटेंशन फैक्टर। लेकिन मुझे संदेह होगा कि टेलर श्रृंखला का उपयोग वास्तव में बहुत तेज है ...
Danvil

1
पॉलिनीयियल फंक्शन सन्निकटन के लिए चेबीशेव टेलर की तुलना में बहुत बेहतर है। टेलर सन्निकटन का उपयोग न करें।
टिम्मम

यहां संख्यात्मक अशुद्ध पेस का एक गुच्छा है; संख्यात्मक और भाजक दोनों जल्दी से बड़े हो जाते हैं और जो फ्लोटिंग-पॉइंट त्रुटियों की ओर जाता है। यह उल्लेख करने के लिए नहीं कि आप कैसे तय करते हैं कि "पर्याप्त सटीकता नहीं है" और इसकी गणना कैसे करें? एक बिंदु के आसपास पड़ोस में टेलर सन्निकटन अच्छा है; उस बिंदु से दूर वे जल्दी से गलत हो जाते हैं और उन्हें बड़ी संख्या में शर्तों की आवश्यकता होती है, यही कारण है कि चेम्बीशेव सन्निकटन के बारे में टिम्म्म का सुझाव (जो किसी दिए गए अंतराल पर अच्छा अनुमान लगाता है) एक अच्छा है।
जेसन एस

2

CEPHES लाइब्रेरी में एक अच्छा समाधान है जो बहुत तेज़ हो सकता है और आप सीपीयू समय को थोड़ा और अधिक लचीले ढंग से सटीकता से जोड़ / हटा सकते हैं।

याद रखें कि cos (x) और sin (x) exp (ix) के वास्तविक और काल्पनिक भाग हैं। इसलिए हम दोनों प्राप्त करने के लिए ऍक्स्प (ix) की गणना करना चाहते हैं। हम 0 और 2pi के बीच y के कुछ असतत मूल्यों के लिए expalculate exp (iy) करते हैं। हम x को अंतराल [0, 2pi) पर शिफ्ट करते हैं। फिर हम उस y को चुनते हैं जो x के सबसे करीब है और
exp (ix) = exp (iy + (ix-iy)) = exp (iy) exp (i (xy)) लिखता है।

हमें लुकअप टेबल से एक्सप (iy) मिलता है। और जब से | xy | छोटा है (y-मानों के बीच की आधी दूरी पर), टेलर श्रृंखला कुछ ही शब्दों में अच्छी तरह से परिवर्तित हो जाएगी, इसलिए हम इसका उपयोग एक्सप (i (xy)) के लिए करते हैं। और फिर हमें एक्स (ix) प्राप्त करने के लिए एक जटिल गुणा की आवश्यकता है।

इसकी एक और अच्छी संपत्ति यह है कि आप इसे SSE का उपयोग करके वेक्टर कर सकते हैं।


2

आप http://gruntthepeon.free.fr/ssemath/ पर एक नज़र डालना चाह सकते हैं , जो CEPHES पुस्तकालय से प्रेरित SSE सदिश कार्यान्वयन प्रदान करता है। इसमें अच्छी सटीकता है (5e-8 के आदेश पर पाप / कॉस से अधिकतम विचलन) और गति (एकल कॉल के आधार पर थोड़ा आउटपरफॉर्म्स fsincos, और कई मूल्यों पर एक स्पष्ट विजेता)।



1

जावास्क्रिप्ट में एक साथ पाप और कॉस फ़ंक्शन का एक सटीक अभी तक तेजी से सन्निकटन, यहां पाया जा सकता है: http://danisraelmalta.github.io/Fmath/ (आसानी से c / c ++ के लिए आयात किया गया)


0

क्या आपने दो कार्यों के लिए लुकअप टेबल घोषित करने के बारे में सोचा है? आपको अभी भी पाप (x) और कॉस (x) की "गणना" करनी होगी, लेकिन यदि आपको उच्च सटीकता की आवश्यकता नहीं है, तो यह निश्चित रूप से तेज़ होगा।


0

MSVC कंपाइलर (आंतरिक) SSE2 फ़ंक्शन का उपयोग कर सकता है

 ___libm_sse2_sincos_ (for x86)
 __libm_sse2_sincos_  (for x64)

यदि उपयुक्त संकलक झंडे निर्दिष्ट किए जाते हैं (न्यूनतम / O2 / मेहराब में: SSE2 / fp: तेज)। इन कार्यों के नाम से प्रतीत होता है कि वे अलग पाप और कोस की गणना नहीं करते हैं, लेकिन दोनों "एक कदम में" हैं।

उदाहरण के लिए:

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

विधानसभा (x86 के लिए) / fp के साथ: तेज:

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

असेंबली (x86 के बिना) / fp के बिना: तेज़ लेकिन / fp के साथ: सटीक इसके बजाय (जो डिफ़ॉल्ट है) अलग पाप और कॉस कॉल करता है:

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: sincos अनुकूलन के लिए उपवास अनिवार्य है।

लेकिन कृपया ध्यान दें

___libm_sse2_sincos_

शायद उतना सटीक नहीं है

__libm_sse2_sin_precise
__libm_sse2_cos_precise

इसके नाम के अंत में "सटीक" गायब होने के कारण।

नवीनतम "MSVC 2019 कंपाइलर" और उपयुक्त अनुकूलन के साथ "थोड़ा" पुराने सिस्टम (Intel Core 2 Duo E6750) पर, मेरा बेंचमार्क दिखाता है कि सिनकोस कॉल अलग पाप और कॉस कॉल की तुलना में 2.4 गुना तेज है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.