سؤال

لا أستطيع رؤية أي اختلاف في الكود بواسطة gcc لتقييد المؤشرات.

file1

void test (int *a, int *b, int *c)
{
  while (*a)
  {
    *c++ = *a++ + *b++; 
  }
}

file2

void test (int *restrict a, int *restrict b, int *restrict c)
{
  while (*a)
  {
    *c++ = *a++ + *b++;
  }
}

جمع مع

  gcc -S -std=c99 -masm=intel file1.c
  gcc -S -std=c99 -masm=intel file2.c

file1.s و file2.s كلاهما نفس الشيء، باستثناء .file السطر الذي يخبرنا باسم الملف:

    .file   "file1.c"
    .text
    .globl  test
    .type   test, @function
test:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    movq    %rdx, -24(%rbp)
    jmp .L2
.L3:
    movq    -8(%rbp), %rax
    movl    (%rax), %edx
    movq    -16(%rbp), %rax
    movl    (%rax), %eax
    addl    %eax, %edx
    movq    -24(%rbp), %rax
    movl    %edx, (%rax)
    addq    $4, -24(%rbp)
    addq    $4, -8(%rbp)
    addq    $4, -16(%rbp)
.L2:
    movq    -8(%rbp), %rax
    movl    (%rax), %eax
    testl   %eax, %eax
    jne .L3
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   test, .-test
    .ident  "GCC: (GNU) 4.6.3 20120306 (Red Hat 4.6.3-2)"
    .section    .note.GNU-stack,"",@progbits

تتم قراءة كل من هذه التعليمات البرمجية من الذاكرة ثم قم بتعيين موقع الذاكرة المشار إليه a ل b.حيث توقعت restrict لن يقوم الإصدار بإعادة قراءة عناوين a و b, ، وعناوين a و b سيتم زيادتها في التسجيل وفي النهاية كتابتها إلى الذاكرة.

هل هناك أي خطأ أفعله؟أم أن اختيار المثال جيد؟

لقد حاولت مع مفاتيح مختلفة -O0, -O1, -O2, -O3, -Ofast, ، و -fstrict-aliasing مع نفس النتائج المتطابقة لكلا الملفين.

ملحوظة: دول مجلس التعاون الخليجي --الإصدار = دول مجلس التعاون الخليجي (دول مجلس التعاون الخليجي) 4.6.3 20120306 (ريد هات 4.6.3-2)

يحرر تم تغيير الرمز.

هل كانت مفيدة؟

المحلول

الشيء هو أن التعبير التالي:

    *c++ = *a++ + *b++;

يحتاج إلى حد كبير إلى إلغاء الإشارة إلى جميع المؤشرات في كل تكرار للحلقة على أي حال، حيث تتغير المؤشرات في كل تكرار.ليس هناك فائدة من الاستخدام restrict.

حاول تغيير الخط داخل الحلقة إلى:

    *c++ = *a++ + *b;

(قد تحتاج أيضًا إلى تمكين التحسينات مثل -O2).

سترى ذلك في restrict حالة تحميله *b في السجل مرة واحدة، بينما في الحالة بدون قيود فإنه يحتاج إلى التحميل من خلال المؤشر في كل تكرار حلقة لأنه لا يعرف ما إذا كان أم لا c الأسماء المستعارة من أي وقت مضى b.

نصائح أخرى

أنت تقرأ فقط من خلال أحد المؤشرات، لذلك restrict لا يهم.

يرى هذا المثال حيث يكون الأمر مهمًا لأن المؤشرات قد تستخدم نفس البيانات، وتتم كتابة البيانات وقراءتها من خلال كلا المؤشرين.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top