2012-06-18 12 views
6

के कारण एसएसई इंट्रिनिक्स के साथ काम करते समय सेगमेंटेशन गलती मैं पहली बार एसएसई इंट्रिनिक्स के साथ काम कर रहा हूं और मुझे 16byte मेमोरी संरेखण सुनिश्चित करने के बाद भी सेगमेंटेशन गलती का सामना करना पड़ रहा है।गलत स्मृति संरेखण

float *V = (float*) memalign(16,dx*sizeof(float)); 

जब मैं यह करने के लिए प्रयास करें::

How to allocate 16byte memory aligned data

यह कैसे मैं अपने सरणी घोषणा की है है: इस पोस्ट में मेरी पहले सवाल का एक विस्तार है

__m128 v_i = _mm_load_ps(&V[i]); //It works 

लेकिन जब मैं ऐसा करता हूं:

__m128 u1 = _mm_load_ps(&V[(i-1)]); //There is a segmentation fault 

लेकिन अगर मैं कार्य करें:

__m128 u1 = _mm_loadu_ps(&V[(i-1)]); //It works again 

हालांकि मैं _mm_loadu_ps का उपयोग कर को खत्म करने और यह केवल _mm_load_ps का उपयोग कर काम करना चाहते हैं करना चाहते हैं।

मैं इंटेल आईसीसी कंपाइलर के साथ काम कर रहा हूं।

मैं इस समस्या को कैसे हल करूं?

अद्यतन:

void FDTD_base (float *V, float *U, int dx, float c0, float c1, float c2, float c3,  float c4) 
    { 
     int i, j, k; 
        for (i = 4; i < dx-4; i++) 
        { 

          U[i] = (c0 * (V[i]) //center 
            + c1 * (V[(i-1)] + V[(i+1)]) 
            + c2 * (V[(i-2)] + V[(i+2)]) 
            + c3 * (V[(i-3)] + V[(i+3)]) 
            + c4 * (V[(i-4)] + V[(i+4)])); 
        } 

     } 

SSE संस्करण:

  for (i=4; i < dx-4; i+=4) 
     { 
      v_i = _mm_load_ps(&V[i]); 
      __m128 center = _mm_mul_ps(v_i,c0_i); 

      __m128 u1 = _mm_loadu_ps(&V[(i-1)]); 
      u2 = _mm_loadu_ps(&V[(i+1)]); 

      u3 = _mm_loadu_ps(&V[(i-2)]); 
      u4 = _mm_loadu_ps(&V[(i+2)]); 

      u5 = _mm_loadu_ps(&V[(i-3)]); 
      u6 = _mm_loadu_ps(&V[(i+3)]); 

      u7 = _mm_load_ps(&V[(i-4)]); 
      u8 = _mm_load_ps(&V[(i+4)]); 

      __m128 tmp1 = _mm_add_ps(u1,u2); 
      __m128 tmp2 = _mm_add_ps(u3,u4); 
      __m128 tmp3 = _mm_add_ps(u5,u6); 
      __m128 tmp4 = _mm_add_ps(u7,u8); 

      __m128 tmp5 = _mm_mul_ps(tmp1,c1_i); 
      __m128 tmp6 = _mm_mul_ps(tmp2,c2_i); 
      __m128 tmp7 = _mm_mul_ps(tmp3,c3_i); 
      __m128 tmp8 = _mm_mul_ps(tmp4,c4_i); 

      __m128 tmp9 = _mm_add_ps(tmp5,tmp6); 
      __m128 tmp10 = _mm_add_ps(tmp7,tmp8); 

      __m128 tmp11 = _mm_add_ps(tmp9,tmp10); 
      __m128 tmp12 = _mm_add_ps(center,tmp11); 

      _mm_store_ps(&U[i], tmp12); 
    } 

वहाँ केवल _mm_load_ps() का उपयोग कर ऐसा करने का एक अधिक कुशल तरीका है

निम्नलिखित कोड में दोनों के संचालन का उपयोग कर?

+0

आपके आर्किटेक्चर पर 'sizeof (float)' क्या है? – ecatmur

+0

@ecatmur: मैं 64 बिट मशीन पर काम कर रहा हूं। – PGOnTheGo

+0

जो प्रश्न का उत्तर नहीं देता है; 64-बिट एबीआई के बहुत सारे हैं। – ecatmur

उत्तर

11

sizeof(float) 4 है, V में केवल प्रत्येक चौथी प्रविष्टि ठीक से गठबंधन की जाएगी। याद रखें कि _mm_load_ps एक समय में चार फ्लोट लोड करता है। तर्क, यानि पहले फ्लोट के सूचक, को 16 बाइट्स के साथ गठबंधन करने की आवश्यकता है।

मुझे लगता है कि आपके उदाहरण में i चार में से एक है, अन्यथा _mm_load_ps(&V[i]) विफल हो जाएगा।

__m128 v_im1; 
__m128 v_i = _mm_load_ps(&V[0]); 
__m128 v_ip1 = _mm_load_ps(&V[4]); 

for (i = 4 ; i < dx ; i += 4) { 

    /* Get the three vectors in this 'frame'. */ 
    v_im1 = v_i; v_i = v_ip1; v_ip1 = _mm_load_ps(&V[i+4]); 

    /* Get the u1..u8 from the example code. */ 
    __m128 u3 = _mm_shuffle_ps(v_im1 , v_i , 3 + (4<<2) + (0<<4) + (1<<6)); 
    __m128 u4 = _mm_shuffle_ps(v_i , v_ip1 , 3 + (4<<2) + (0<<4) + (1<<6)); 

    __m128 u1 = _mm_shuffle_ps(u3 , v_i , 1 + (2<<2) + (1<<4) + (2<<6)); 
    __m128 u2 = _mm_shuffle_ps(v_i , u4 , 1 + (2<<2) + (1<<4) + (2<<6)); 

    __m128 u5 = _mm_shuffle_ps(v_im1 , u3 , 1 + (2<<2) + (1<<4) + (2<<6)); 
    __m128 u6 = _mm_shuffle_ps(u4 , v_ip1 , 1 + (2<<2) + (1<<4) + (2<<6)); 

    __m128 u7 = v_im1; 
    __m128 u8 = v_ip1; 

    /* Do your computation and store. */ 
    ... 

    } 

ध्यान दें कि यह एक सा मुश्किल है, क्योंकि _mm_shuffle_ps केवल दो मान ले जा सकते हैं:

अद्यतन

यह मैं कैसे गठबंधन भार और शफ़ल का उपयोग कर रपट ऊपर खिड़की उदाहरण को लागू करने का सुझाव देते हैं है प्रत्येक तर्क से, यही कारण है कि हमें पहले विभिन्न ओवरलैप के साथ अन्य मानों के लिए पुनः उपयोग करने के लिए u3 और u4 बनाने की आवश्यकता है।

भी ध्यान रखें कि मूल्यों u1, u3, और u5 भी u2, u4 और u6 से पिछले चरण में बरामद किया जा सकता।

नोट, आखिरकार, मेरे पास है ऊपर दिए गए कोड सत्यापित नहीं है! _mm_shuffle_ps के लिए प्रलेखन पढ़ें और जांचें कि तीसरा तर्क, चयनकर्ता, प्रत्येक मामले के लिए सही है।

+0

पेड्रो: आप सही हैं। मैं अपने उदाहरण में 4 का एक बहुमत है। लेकिन मैं सेगमेंटेशन गलती को कैसे दूर करूं? – PGOnTheGo

+0

@Hello_PG: यह उस पर निर्भर करता है कि आप क्या करना चाहते हैं। क्या आपको चार समूहों में 'वी' के सभी तत्वों पर सिमड ऑपरेशंस करना है, उदाहरण के लिए 'वी [0..3]', 'वी [4..7]', 'वी [8..11]'? या आपके पास लंबाई चार की एक स्लाइडिंग विंडो है, उदाहरण के लिए 'वी [0..3]', 'वी [1..4]', 'वी [2..5]'? पूर्व मामले में, आप केवल 'i' पर 'लूप' का उपयोग कर सकते हैं, प्रत्येक पुनरावृत्ति में 'i''' i' बढ़ाकर। बाद के मामले में, आप कम कुशल unaligned '_mm_loadu_ps' के साथ अटक गए हैं। – Pedro

+0

मेरे कोड में एक स्लाइडिंग विंडो अवधारणा शामिल है। असल में यह एक 1 डी स्टैंसिल है, जिसके लिए मुझे पड़ोसी 4 तत्वों को ट्रैक करने की आवश्यकता होती है। मैंने _mm_load_ps और _mm_loadu_ps दोनों का उपयोग करके कोड अपडेट किया है .. कृपया मेरे अपडेट किए गए पोस्ट में कोड पाएं। क्या इससे निपटने का यह सबसे अच्छा तरीका है? – PGOnTheGo

संबंधित मुद्दे