2016-02-29 5 views
5

काम कर यहाँ से जीसीसी __restrict__ क्वालीफायर बंद हो जाता है काफी कुछ सरल कोड, -O2 साथ संकलित (जीसीसी 4.8.5) है:क्या

unsigned char * linebuf; 
int yuyv_tojpegycbcr(unsigned char * buf, int w) 
{ 
    int col; 
    unsigned char * restrict pix = buf; 
    unsigned char * restrict line = linebuf; 

    for(col = 0; col < w - 1; col +=2) 
    { 
      line[col*3] = pix[0]; 
      line[col*3 + 1] = pix[1]; 
      line[col*3 + 2] = pix[3]; 
      line[col*3 + 3] = pix[2]; 
      line[col*3 + 4] = pix[1]; 
      line[col*3 + 5] = pix[3]; 
      pix += 4; 
    } 
    return 0; 
} 

और यहाँ इसी विधानसभा है:

0000000000000000 <yuyv_tojpegycbcr>: 
    0: 83 fe 01    cmp $0x1,%esi 
    3: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax  # a <yuyv_tojpegycbcr+0xa> 
    a: 7e 4e     jle 5a <yuyv_tojpegycbcr+0x5a> 
    c: 83 ee 02    sub $0x2,%esi 
    f: 31 d2     xor %edx,%edx 
    11: d1 ee     shr %esi 
    13: 48 8d 74 76 03   lea 0x3(%rsi,%rsi,2),%rsi 
    18: 48 01 f6    add %rsi,%rsi 
    1b: 0f 1f 44 00 00   nopl 0x0(%rax,%rax,1) 
    20: 0f b6 0f    movzbl (%rdi),%ecx 
    23: 48 83 c2 06    add $0x6,%rdx 
    27: 48 83 c7 04    add $0x4,%rdi 
    2b: 48 83 c0 06    add $0x6,%rax 
    2f: 88 48 fa    mov %cl,-0x6(%rax) 
    32: 0f b6 4f fd    movzbl -0x3(%rdi),%ecx 
    36: 88 48 fb    mov %cl,-0x5(%rax) 
    39: 0f b6 4f ff    movzbl -0x1(%rdi),%ecx 
    3d: 88 48 fc    mov %cl,-0x4(%rax) 
    40: 0f b6 4f fe    movzbl -0x2(%rdi),%ecx 
    44: 88 48 fd    mov %cl,-0x3(%rax) 
    47: 0f b6 4f fd    movzbl -0x3(%rdi),%ecx 
    4b: 88 48 fe    mov %cl,-0x2(%rax) 
    4e: 0f b6 4f ff    movzbl -0x1(%rdi),%ecx 
    52: 88 48 ff    mov %cl,-0x1(%rax) 
    55: 48 39 f2    cmp %rsi,%rdx 
    58: 75 c6     jne 20 <yuyv_tojpegycbcr+0x20> 
    5a: 31 c0     xor %eax,%eax 
    5c: c3      retq 

जब प्रतिबंधित क्वालीफायर के बिना संकलित, आउटपुट समान है: बहुत सारे इंटरमीस्ड लोड और स्टोर। कुछ मान दो बार लोड होते हैं, और ऐसा लगता है कि कोई अनुकूलन नहीं हुआ है। यदि pix और line अनियमित हैं, तो मुझे उम्मीद है कि संकलक पर्याप्त स्मार्ट हो, और अन्य चीजों के बीच केवल पिक्स [1] और पिक्स [3] लोड हो जाए।

क्या आप restrict क्वालीफायर को अयोग्य घोषित कर सकते हैं?

पीएस: एक अन्य आर्किटेक्चर (बांह v7) पर, एक नया जीसीसी (4.9.2) के साथ, परिणाम समान है। उत्पन्न कोड के साथ और बिना प्रतिबंधित के तुलना करने के लिए यहां एक टेस्ट स्क्रिप्ट है।

#!/bin/sh 
gcc -c -o test.o -std=c99 -O2 yuyv_to_jpegycbcr.c 
objdump -d test.o > test.S 


gcc -c -o test2.o -O2 -D restrict='' yuyv_to_jpegycbcr.c 
objdump -d test2.o > test2.S 
+0

कोई कारण नहीं है कि आप मानक 'प्रतिबंधित' योग्यता का उपयोग नहीं करते हैं? – Olaf

+0

क्योंकि std = c99 का उपयोग करके मेरा कोड तोड़ता है, शायद इसलिए कि मैंने वैध सुविधा_test_macros सेट नहीं किया है। मैं इसे ठीक कर सकता हूं लेकिन मुझे नहीं लगता कि इससे कोई फर्क पड़ता है। – shodanex

+0

आपको वेक्टरेशन के साथ-साथ यहां उम्मीद करनी चाहिए (उस उपकरण को मानना ​​जिसे आप संकलित करने के लिए संकलित कर रहे हैं)। – marko

उत्तर

4

स्थानीय चर के बजाए फ़ंक्शन पैरामीटर पर प्रतिबंध रखें।

मेरे अनुभव से, अधिकांश कंपाइलर (जीसीसी समेत) केवल तभी उपयोग करते हैं जब यह फ़ंक्शन पैरामीटर पर निर्दिष्ट होता है। फ़ंक्शन के भीतर स्थानीय चर पर सभी उपयोगों को अनदेखा कर दिया जाता है।

मुझे संदेह है कि इसे मूल-ब्लॉक स्तर की बजाय कार्य-स्तर पर किए गए एलियासिंग विश्लेषण के साथ करना है। लेकिन मेरे पास इसका समर्थन करने के लिए कोई सबूत नहीं है। इसके अलावा, यह शायद कंपाइलर और कंपाइलर संस्करण से भिन्न होता है।

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

+1

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60712 पर प्रति टिप्पणी, ऐसा लगता है कि जीसीसी केवल फ़ंक्शन पैरामीटर – shodanex

+0

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

+0

और कभी-कभी जब मैं एक अलग स्थिर कार्य घोषित करता हूं तो संकलक एक खराब परिणाम देता है। कभी-कभी मुझे एक अलग ऑब्जेक्ट फ़ाइल में प्रतिबंधित के साथ आंतरिक फ़ंक्शन घोषित करना होता है। तो आपको वही करना होगा जो आप कहते हैं: पहली बार असेंबली की जांच करें और प्रत्येक अपग्रेड या कंपाइलर परिवर्तन करें। –