SORU
31 Temmuz 2014, PERŞEMBE


Boş döngü, C boş olmayan bir tane daha yavaştır

C kodu bir satır çalıştırmak için kullanılan ne bilmek isterken, garip bir şey fark ettim :

int main (char argc, char * argv[]) {
    time_t begin, end;
    uint64_t i;
    double total_time, free_time;
    int A = 1;
    int B = 1;

    begin = clock();
    for (i = 0; i<(1<<31)-1; i  );
    end = clock();
    free_time = (double)(end-begin)/CLOCKS_PER_SEC;
    printf("%f\n", free_time);

    begin = clock();
    for (i = 0; i<(1<<31)-1; i  ) {
        A  = B%2;
    }
    end = clock();
    free_time = (double)(end-begin)/CLOCKS_PER_SEC;
    printf("%f\n", free_time);

    return(0);
}

Çalıştırıldığında hangi görüntüler :

5.873425
4.826874

Neden boş döngü bir yönerge içinde olan ikinci ve daha fazla zaman kullanır ? Elbette pek çok çeşidi denedim ama her seferinde, boş bir döngü içinde tek bir talimat ile daha fazla zaman alır.

Döngüler sipariş değiştirme ve bazı ısınma kod ekleyerek denedim ve sorunum hiç değişmedi unutmayın.

Ben kullanıyorum IDE olarak codeblocks ile GNU gcc derleyici, linux ubuntu 14.04 ve bir quadcore ıntel ı5 de 2.3 GHz (denedim çalışan program üzerinde bir tek çekirdek, bu sonucu değiştirmez).

CEVAP
31 Temmuz 2014, PERŞEMBE


Kod 32 bit bir tamsayı kullanır varsayarak int tip sistem muhtemelen yapar), sonra da hiçbir şey kodunuzu tespit edilebilir. Bunun yerine,bu tanımsız davranış sergiler.

foo.c:5:5: error: first parameter of 'main' (argument count) must be of type 'int'
int main (char argc, char * argv[]) {
    ^
foo.c:13:26: warning: overflow in expression; result is 2147483647 with type 'int' [-Winteger-overflow]
    for (i = 0; i<(1<<31)-1; i  );
                         ^
foo.c:19:26: warning: overflow in expression; result is 2147483647 with type 'int' [-Winteger-overflow]
    for (i = 0; i<(1<<31)-1; i  ) {
                         ^

Hadi bunu düzeltmek için deneyin:

#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <limits.h>

int main (int argc, char * argv[]) {
    time_t begin, end;
    uint64_t i;
    double total_time, free_time;
    int A = 1;
    int B = 1;

    begin = clock();
    for (i = 0; i<INT_MAX; i  );
    end = clock();
    free_time = (double)(end-begin)/CLOCKS_PER_SEC;
    printf("%f\n", free_time);

    begin = clock();
    for (i = 0; i<INT_MAX; i  ) {
        A  = B%2;
    }
    end = clock();
    free_time = (double)(end-begin)/CLOCKS_PER_SEC;
    printf("%f\n", free_time);

    return(0);
}

Simdi bu kod derleme çıktı bak. Şahsen ben göstermek için gidiyorum bu yüzden LLVM iç aksamı çok okunabilir buluyorum. Çalıştırarak üretmek, ..

clang -O3 foo.c -S -emit-llvm -std=gnu99

İşte çıkış ilgili bölümünü (ana fonksiyon):

define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 {
  %1 = tail call i64 @"\01_clock"() #3
  %2 = tail call i64 @"\01_clock"() #3
  %3 = sub nsw i64 %2, %1
  %4 = sitofp i64 %3 to double
  %5 = fdiv double %4, 1.000000e 06
  %6 = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), double %5) #3
  %7 = tail call i64 @"\01_clock"() #3
  %8 = tail call i64 @"\01_clock"() #3
  %9 = sub nsw i64 %8, %7
   = sitofp i64 %9 to double
   = fdiv double , 1.000000e 06
   = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), double ) #3
  ret i32 0
}

Olduğunu unutmayınhayır13* *için çağrıları arasında işlemlerher iki durumda da. Hem derlenmiştam olarak aynı şey.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • A Alkhaldi

    A Alkhaldi

    12 Mayıs 2007
  • AlaskanGrizzly

    AlaskanGrizz

    30 EKİM 2009
  • Apple&Tech Reviews & Giveaways

    Apple&Tech R

    12 Temmuz 2008