2009-08-08 13 views
7

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

मैं ऐसी स्थिति में हूं जहां मुझे कुछ डेटा पर लूप की आवश्यकता है, और मैं अपनी गणना में निरंतर कारक का उपयोग करता हूं। मैं लूप के दौरान एक सुरक्षित रजिस्टर में उस कारक को दूर रखना चाहता हूं, इसलिए मुझे इसे हर बार फिर से लोड करने की आवश्यकता नहीं है।

कुछ कोड के साथ स्पष्ट करने के लिए:

struct vect2 { 
    fltpt x; 
    fltpt y; 
}__attribute__((aligned(16))); /* Align on 16B boundary for SSE2 instructions */ 
typedef struct vect2 vect2_t; 


void function() 
{ 
    /* get a specific value set up in xmm1, and keep it there for the 
    * rest of the loop. */ 
    for(int i = 0, i<N; i++){ 
     asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
     ); 
    } 
} 

मैं "रजिस्टर" कीवर्ड के साथ कुछ कर रही कोशिश की है। लेकिन अगर मुझे गलत नहीं लगता है, तो ऐसा लगता है कि मैं केवल उस संरचना (एक सामान्य रजिस्टर में) पॉइंटर को संरक्षित कर सकता हूं। बहुमूल्य समय बर्बाद करने के लिए, हर पुनरावृत्ति को संदर्भित करने की आवश्यकता होगी।

register vect2_t hVect asm("xmm1") = {h, h}; 
/* Gives error: data type of 'hVect' isn't suitable for a register */ 

register vect2_t *hVect2 asm("rax"); 
*hVect2 = (vect2_t){h,h}; 
/* Seems to work, but not what I'm looking for */ 

मैं सिर्फ ग्रहण करने के लिए है कि जीसीसी रजिस्टर xmm1 परिवर्तन नहीं होगा पसंद नहीं है, यह :-) कुछ ऐसी बातें एक "एक नाक से बाहर उड़ान राक्षसों" की बहुत अधिक है। तो मुझे आशा है कि ऐसा करने का एक उचित तरीका है।

उत्तर

8

मुझे लगता है कि यहां समाधान यह है कि जीसीसी को यह पता होना चाहिए कि आपका vec2_t प्रकार वास्तव में एक वेक्टर है; तो तुम सिर्फ पाश-अपरिवर्तनीय मूल्य की गणना और एक सामान्य चर के रूप में यह इलाज (सिवाय संकलक जानता है कि यह एक वेक्टर प्रकार है) कर सकते हैं:

typedef double vec2_t __attribute__ ((vector_size (16))); 

void function() 
{ 
    /* get a specific value set up, e.g. */ 
    vec2_t invariant; 
    asm("some calculations, soring result in invariant." 
     : "=x" (invariant)); 

    for(int i = 0; i<N; i++){ 
    asm(
      "Some calculations;" 
      "on an element of;" 
      "a data set.;" 
      "The value in xmm1;" 
      "is needed;" 
      : "x" (invariant) // and other SSE arguments 
     ); 
    } 
} 

मैं सिर्फ इस लूप के अंदर एक साधारण गणना के साथ संकलित, और कम से कम अनुकूलन स्तर 1 के साथ invariant का मान लूप के दौरान एक्सएमएम रजिस्टर में रखा जाता है।

(यह सब मानते हैं कि आप एक स्पष्ट एक्सएमएम रजिस्टर में अपने लूप इनवेरिएंट की आवश्यकता है; और आप जीसीसी के सामान्य रजिस्टर आवंटन का उपयोग कर सकते हैं)।

3

मुझे लगता है कि संकलक को पंजीकरण असाइनमेंट छोड़ना सबसे अच्छा है। यह शायद आपके से बेहतर ट्रैक रख सकता है। जीसीसी पहले से ही एसएसई एक्सटेंशन का उपयोग करेगा लेकिन यदि आप सुनिश्चित हैं कि आप बेहतर जानते हैं, तो जीसीसी __builtin कार्यों का उपयोग करें। ईमानदार होने के लिए, मुझे थोड़ा सा संदेह है कि आप इसे इस तरह से तेज बना देंगे।

शुभकामनाएँ!

ये साइटें देखने के लिए शायद दिलचस्प हैं।

GCC X86 Built-in functions

Working with SIMD with GCC

3

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

शून्य कार्य (शून्य); // सी

बाहरी "सी" फ़ंक्शन (शून्य); // सी ++