2009-10-19 8 views
11

मैंने सी, पायथन और ओकैमल में एक मूल Hippity Hop प्रोग्राम लिखा था। माना जाता है कि यह शायद इन तीन भाषाओं का एक बहुत अच्छा बेंचमार्क नहीं है।यह ओकैम प्रोग्राम मेरे सी प्रोग्राम से तेज़ क्यों है?

  • पायथन: 0.350 सेकंड
  • सी: .050 सेकंड
  • व्याख्या OCaml: .040 सेकंड
  • संकलित OCaml: लेकिन परिणाम मुझे मिल गया कुछ इस तरह थे .010

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

सी

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 

long get_count(char *name); 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2){ 
    printf("Filename must be specified as a positional argument.\n"); 
    exit(EXIT_FAILURE); 
    } 

    long count_no = get_count(argv[1]); 

    int i; 
    for (i = 1; i <= count_no; i++){ 
    if (((i % 3) == 0) && ((i % 5) == 0)){ 
     printf("Hop\n"); 
     continue; 
    } 
    if ((i % 3) == 0){ 
     printf("Hoppity\n"); 
    } 
    if ((i % 5) == 0){ 
     printf("Hophop\n"); 
    } 
    } 
    return 0; 
} 

long get_count(char *name){ 
    FILE *fileptr = fopen(name, "r"); 
    if (!fileptr){ 
    printf("Unable to open file %s.\n", name); 
    exit(EXIT_FAILURE); 
    } 
    size_t text_len = 20; 
    char *file_text = calloc(text_len, sizeof(char)); 
    while (!feof(fileptr)){ 
    fread(file_text, sizeof(char), text_len, fileptr); 
    assert(!ferror(fileptr)); 
    text_len += 20; 
    file_text = realloc(file_text, text_len * sizeof(char)); 
    } 
    long file_as_int = strtol(file_text, NULL, 10); 

    free(file_text); 
    return file_as_int; 
} 

OCaml

open String;; 

let trim str = 
    if str = "" then "" else 
    let search_pos init p next = 
    let rec search i = 
     if p i then raise(Failure "empty") else 
     match str.[i] with 
     | ' ' | '\n' | '\r' | '\t' -> search (next i) 
     | _ -> i 
    in 
    search init 
    in 
    let len = String.length str in 
    try 
    let left = search_pos 0 (fun i -> i >= len) (succ) 
    and right = search_pos (len - 1) (fun i -> i < 0) (pred) 
    in 
    String.sub str left (right - left + 1) 
    with 
    | Failure "empty" -> "" 
;; 

let rec iterate_over_numbers curr_num max_num = 
    (
    if curr_num <= max_num then (
    if ((curr_num mod 3) == 0) && ((curr_num mod 5) == 0) then 
     print_endline "Hop" 
    else if (curr_num mod 3) == 0 then 
     print_endline "Hoppity" 
    else if (curr_num mod 5) == 0 then 
     print_endline "Hophop"; 
    iterate_over_numbers (curr_num + 1) max_num 
    )) 
;; 


let fname = Sys.argv.(1);; 
let infile = open_in fname;; 
let file_text = trim (input_line infile);; 
close_in infile;; 
let input_number = int_of_string file_text;; 
iterate_over_numbers 1 input_number;; 

लेकिन मुझे पता है कि मैं क्यों इन परिणामों हो रही है उत्सुक हूँ। क्या मैं अपने सी प्रोग्राम में कुछ गूंगा कर रहा हूं, या क्या यह सिर्फ ओकैमल कुछ तेज है? मुझे थोड़ा अजीब लगता है कि एक व्याख्या प्रोग्राम सी संस्करण की तुलना में थोड़ा तेज चल रहा है, और संकलित प्रोग्राम तेजी से 5 गुना चल रहा है।

+0

सी संस्करण के लिए आप किस कंपाइलर स्विच का उपयोग करते थे? –

+0

@ जोनाथन - मैंने अभी 'gcc -o hoppity main.c' किया है। मैंने ईमानदार होने के लिए अनुकूलन स्तर स्थापित करने के बारे में नहीं सोचा था। :-) –

+0

परीक्षण चलाए जाने पर फ़ाइल में संख्या क्या थी? और क्या आउटपुट किसी फ़ाइल या पाइप को सभी परीक्षणों के लिए रीडायरेक्ट किया गया था? और 'gcc' और 'gcc -O' के साथ सापेक्ष प्रदर्शन को जानना दिलचस्प होगा। –

उत्तर

8

आपका सी कोड OCaml कोड के बराबर नहीं है - आप 'शेष है, तो' OCaml में काफी इतना moduli recompute करने से बचने के लिए इस्तेमाल किया।

'लंबे पूर्णांक को पढ़ने' में बहुत भयानक कोड है। क्यों न केवल fscanf() का उपयोग करें; यह रिक्त स्थान और स्वचालित रूप से सभी को छोड़ देता है, और आपको malloc() आदि से बचाता है। मैं अक्सर fscanf() का उपयोग करने की सलाह नहीं देता, लेकिन यह इसके लिए एक सेटअप की तरह दिखता है - एक पंक्ति, संभवतः रिक्त स्थान के साथ, कोई मजेदार सामान नहीं।


जिज्ञासा बिल्ली को मार डाला - लेकिन इस मामले में, तेंदुए नहीं।

मै मैकोज़ एक्स इंटेल के लिए ओकैमल 3.11.1 डाउनलोड किया और प्रश्न से ओसीएमएल कोड को xxx.ml (ओकैमल) में कॉपी किया, और इसे ऑब्जेक्ट फ़ाइल xxx में संकलित किया ("ocamlc -o xxx xxx.ml" का उपयोग करके) ; मैंने सी कोड वर्बैटिम को yyy.c में कॉपी किया और fscanf() और fclose() का उपयोग करके एक variant zzz.c बनाया, और उन्हें "gcc -O -o yyy yyy.c" और "gcc -O -o zzz zzz.c" का उपयोग करके संकलित किया। मैंने एक फाइल 'file3' बनाई है जिसमें "987654" प्लस एक नई लाइन है। मैंने दिखाए गए एक शेल स्क्रिप्ट runthem.sh बनाया है। ध्यान दें कि 'टाइम' एक पस्की कमांड है जो सोचता है कि इसका आउटपुट स्टडरर पर जाना चाहिए, भले ही आप इसे नहीं चाहते थे - आपको आउटपुट प्राप्त करने के लिए काफी मेहनत करनी होगी जहां आप इसे जाना चाहते हैं। (रेंज आदेश दी गई श्रेणी में नंबर, समावेशी उत्पन्न करता है -। इसलिए कार्यक्रम प्रति 11 मूल्यों)

Osiris JL: cat runthem.sh 
for prog in "ocaml xxx.ml" ./xxx ./yyy ./zzz 
do 
    for iter in $(range 0 10) 
    do 
     r=$(sh -c "time $prog file3 >/dev/null" 2>&1) 
     echo $prog: $r 
    done 
done 
Osiris JL: 

मैं पर एक आधुनिक मैकबुक प्रो यह सब भाग गया (3 गीगा कोर 2 डुओ आदि, 4 जीबी रैम) चल तेंदुए (10.5.8)। मुझे मिलने वाले समय दिखाए गए हैं:

Osiris JL: sh runthem.sh 
ocaml xxx.ml: real 0m0.961s user 0m0.524s sys 0m0.432s 
ocaml xxx.ml: real 0m0.953s user 0m0.516s sys 0m0.430s 
ocaml xxx.ml: real 0m0.959s user 0m0.517s sys 0m0.431s 
ocaml xxx.ml: real 0m0.951s user 0m0.517s sys 0m0.430s 
ocaml xxx.ml: real 0m0.952s user 0m0.516s sys 0m0.431s 
ocaml xxx.ml: real 0m0.952s user 0m0.514s sys 0m0.431s 
ocaml xxx.ml: real 0m0.951s user 0m0.515s sys 0m0.431s 
ocaml xxx.ml: real 0m0.959s user 0m0.515s sys 0m0.431s 
ocaml xxx.ml: real 0m0.950s user 0m0.515s sys 0m0.431s 
ocaml xxx.ml: real 0m0.956s user 0m0.516s sys 0m0.431s 
ocaml xxx.ml: real 0m0.952s user 0m0.514s sys 0m0.432s 
./xxx: real 0m0.928s user 0m0.494s sys 0m0.430s 
./xxx: real 0m0.938s user 0m0.494s sys 0m0.430s 
./xxx: real 0m0.927s user 0m0.494s sys 0m0.430s 
./xxx: real 0m0.928s user 0m0.492s sys 0m0.430s 
./xxx: real 0m0.928s user 0m0.493s sys 0m0.430s 
./xxx: real 0m0.927s user 0m0.493s sys 0m0.430s 
./xxx: real 0m0.928s user 0m0.492s sys 0m0.430s 
./xxx: real 0m0.933s user 0m0.497s sys 0m0.428s 
./xxx: real 0m0.926s user 0m0.494s sys 0m0.429s 
./xxx: real 0m0.921s user 0m0.492s sys 0m0.428s 
./xxx: real 0m0.925s user 0m0.494s sys 0m0.428s 
./yyy: real 0m0.027s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.031s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.029s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.029s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.031s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.030s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
Osiris JL: 

मुझे ओ कोडल कोड सी कोड से तेज़ी से चल रहा नहीं है। मैं फ़ाइल में छोटी संख्याओं के साथ परीक्षण है कि पढ़ा गया था भाग गया, और परिणाम सी कोड के पक्ष में इसी तरह थे:

स्टॉप संख्या: 345

ocaml xxx.ml: real 0m0.027s user 0m0.020s sys 0m0.005s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.005s 
ocaml xxx.ml: real 0m0.025s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.020s user 0m0.015s sys 0m0.003s 
ocaml xxx.ml: real 0m0.022s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.019s user 0m0.015s sys 0m0.003s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.020s user 0m0.015s sys 0m0.004s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.020s user 0m0.015s sys 0m0.004s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.004s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.002s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.002s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.005s user 0m0.001s sys 0m0.002s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.002s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.003s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.001s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.003s user 0m0.000s sys 0m0.002s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.001s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.003s user 0m0.000s sys 0m0.002s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 

स्टॉप संख्या: 87654

ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.101s user 0m0.060s sys 0m0.040s 
ocaml xxx.ml: real 0m0.103s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.101s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.103s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.101s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.105s user 0m0.059s sys 0m0.041s 
./xxx: real 0m0.092s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.087s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.084s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.086s user 0m0.045s sys 0m0.039s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.084s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.084s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.083s user 0m0.044s sys 0m0.038s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.005s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.005s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.006s user 0m0.003s sys 0m0.002s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.005s user 0m0.003s sys 0m0.002s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.005s user 0m0.003s sys 0m0.001s 

जाहिर है, वाईएमएमवी - लेकिन ऐसा प्रतीत होता है कि ओकैमल एक काफी मार्जिन से सी से धीमा है, लेकिन अगर दी गई फ़ाइल में संख्या पर्याप्त छोटा है, तो शुरू करें और प्रक्रिया पढ़ने पर प्रक्रिया को हावी करें।

सी समय, विशेष रूप से छोटी संख्याओं पर, इतनी तेजी से हैं कि वे सभी विश्वसनीय नहीं हैं।

+0

एफवाईआई, इनमें से कोई भी एक बड़ा प्रदर्शन अंतर नहीं हुआ है। हालांकि fscanf का उपयोग कोड को एक बहुत अधिक पठनीय बनाता है! –

+0

दिलचस्प: जैसा कि मैंने मुख्य प्रश्न पर टिप्पणियों में पूछा - आपको कितनी बड़ी संख्या दी गई थी?और क्या होता है यदि आप एन बार फिर से शुरू करते हैं (जहां एन सेकंड के क्रम का समय लेने के लिए सबसे तेज़ प्रोग्राम प्राप्त करने के लिए पर्याप्त संख्या है)? भूलें कि अगर आप 10,000 पुनरावृत्तियों करते हैं तो आपको फ़ाइल को बंद करने की आवश्यकता होगी। –

8

0.05 के तहत समय एक साधारण शोर हो सकता है। वास्तव में सी में निष्पादन समय के ~ 1s प्राप्त करने के लिए मुख्य कार्यक्रम को दोहराएं (मेरा मतलब है कि इसे प्रोग्राम में लूप में दोहराएं, इसे फिर से चलाकर नहीं)

क्या आपने ऑप्टिमाइज़ेशन के साथ अपना कोड संकलित किया था? क्या आपने शाखाओं की संख्या को कम करने की कोशिश की? (और तुलना)

if (i % 3 == 0) { 
    if (i % 5 == 0) { 
    printf("Hop\n"); 
    continue; 
    } 
    printf("Hoppity\n"); 
} else if (i % 5 == 0){ 
    printf("Hophop\n"); 
} 

क्या आपने असेंबलर आउटपुट को देखने का प्रयास किया था?

इसके अलावा printf बहुत धीमी है। इसके बजाय puts("Hop") आज़माएं, क्योंकि आप किसी भी तरह से फॉर्मेटिंग का उपयोग नहीं करते हैं।

+0

यह संभव है, लेकिन आपको इसका परीक्षण करना होगा । जिस समय आप हर 15 वें प्रयास में सहेजते हैं (आप केवल 1 चेक करते हैं) उस समय को संतुलित नहीं कर सकता है जब आप 3 चेक करते हैं। केवल परीक्षण ही बता सकता है :) (मुझे% 15, i% 3, i% 5 की जांच करने के लिए एक सुझाव पर टिप्पणी की गई - इसे बाद में हटा दिया गया था) – viraptor

+0

हाँ, मैंने इसे कोड में टाइपो के कारण हटा दिया, फिर शायद इसे एहसास हुआ अधिक कुशल नहीं होगा, इसलिए मैंने इसे हटा दिया। –

+0

इस प्रकार, अगर मैं अनुकूलन स्तर को चालू करता हूं तो यह एक * बहुत * तेज लगता है। –

1

मुझे यह देखने में दिलचस्पी होगी कि get_count() में कितना समय व्यतीत किया जाता है।

मुझे यकीन नहीं है कि इससे कोई फर्क नहीं पड़ता है, लेकिन आप एक स्ट्रिंग के रूप में लंबे समय तक पढ़ रहे हैं, जिसका अर्थ है कि स्ट्रिंग 20 बाइट्स से अधिक नहीं हो सकती है, या 10 बाइट्स (2^64 = कुछ 20 वर्ण लंबा दशमलव संख्या, या 2^32 = कुछ 10 वर्ण लंबे दशमलव संख्या), इसलिए आपको get_count में अपने लूप की आवश्यकता नहीं है। साथ ही, आप कॉलक को कॉल करने के बजाए स्टैक पर file_text आवंटित कर सकते हैं - लेकिन मुझे लगता है कि आपको अभी भी इसे शून्य करने की आवश्यकता होगी, या अन्यथा लंबाई ढूंढें और अंतिम बाइट को शून्य पर सेट करें।

file_length = lseek(fileptr, 0, SEEK_END); 
+0

दिलचस्प बिंदु। मुझे लगता है कि बार-बार स्मृति को फिर से आवंटित करना बहुत अक्षम होगा। मुझे लगता है कि मुझे सी प्रोफाइलर से परिचित होने की जरूरत है। :-) –

+0

स्थानीय चर के ऊपर जोनाथन के fscanf सुझाव का उपयोग करके, ऐसा नहीं लगता है कि इससे एक बड़ा अंतर आया है। –

1

कोई भी प्रोग्राम जिसमें अधिकतर फ़ाइल खोलना और इसे पढ़ना शामिल है, फ़ाइल खोलने और इसे पढ़ने की गति से सीमित है। सी कंप्यूटेशंस जो आप यहां कर रहे हैं, फाइल खोलने और इसे पढ़ने के समय 1 मिलियन और एक हज़ारवां के बीच ले जाएगा।

मैंने सोचा था कि इस साइट उपयोगी था: http://norvig.com/21-days.html#answers

+0

यदि यह सत्य था, तो सी और ओकैमल के बीच ऐसी कोई विसंगति नहीं होगी (क्योंकि दोनों डिस्क IO से बंधे हैं)। ओपी ने संकेत दिया है कि जब वह अनुकूलन स्तर बदल गया तो सी कोड बहुत तेज़ हो गया, इसलिए मुझे संदेह है कि यह समस्या हो सकती है। –

+0

लेकिन फ़ाइल तक पहुंचने में लगने वाला समय पूरी तरह यादृच्छिक है। अगर फ़ाइल अभी भी कैश की गई है तो प्रोग्राम को ठंडा होने की तुलना में बहुत कम समय लगेगा। यदि वह ओकैमल पहले और सी सेकेंड चलाता है, तो सी शायद जीत जाएगा। यदि वह सी प्रोग्राम को दस लाख से अधिक बार चलाता है, तो औसत समय बहुत महत्वपूर्ण हो जाएगा। –

+0

@ किनोपिको - मैं वास्तव में एक ही फ़ाइल के डुप्लिकेट के खिलाफ इन्हें चला रहा हूं। –

2

इस तरह के एक छोटे से कार्यक्रम में, यह अनुमान लगाना मुश्किल होता है कि चीजें किस तरह से काम करती हैं। मुझे लगता है कि अगर मैं इसे कर रहा था, मैं इस तरह कोड लिखने चाहते हैं (त्रुटि पल के लिए जाँच बाहर छोड़कर):

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) { 
    static char buffer[20]; 
    int limit, i; 

    freopen(argv[1], "r", stdin); 
fgets(buffer, sizeof(buffer), stdin); 
    limit = atoi(buffer); 

    for (i=1; i<=limit; i++) { 
     int div3=i%3==0; 
     int div5=i%5==0; 
     if (div3 && div5) 
      puts("Hop"); 
     else if (div3) 
      puts("Hoppity"); 
     else if (div5) 
      puts("HopHop"); 
    } 
    return 0; 
} 

का उपयोग freopen अन्य फ़ाइल धारा बनाने बचा जाता है, और इसके बजाय सिर्फ निर्दिष्ट करने के लिए मानक इनपुट से जोड़ता है फ़ाइल। कोई गारंटी नहीं है कि यह तेज़ है, लेकिन वैसे भी धीमा होने की संभावना नहीं है।

इसी तरह, एक अच्छा कंपाइलर नोट कर सकता है कि i पूरे लूप बॉडी में निरंतर है, और दो शेष परिचालनों को कारक बनाता है, इसलिए यह केवल एक बार होता है। यहां मैंने इसे हाथ से किया है, जो कि कोई तेज़ नहीं हो सकता है, लेकिन लगभग निश्चित रूप से धीमा नहीं होगा।

के बजाय puts का उपयोग करना काफी समान है - यह कोई तेज़ नहीं हो सकता है, लेकिन यह लगभग निश्चित रूप से धीमा नहीं होगा।यदि आप रूपांतरण मांग रहे हैं, तो printf का उपयोग करके, इसे '%' की तलाश में पूरी स्ट्रिंग को स्कैन करना होगा, लेकिन puts कोई रूपांतरण नहीं करता है, इसलिए ऐसा नहीं करना है ।

इस तरह के एक छोटे से कार्यक्रम के साथ, एक और कारक है जो काफी महत्वपूर्ण हो सकता है: puts आमतौर पर printf से काफी छोटा होगा। आपने यह नहीं कहा है कि आप समय कैसे कर रहे हैं, लेकिन यदि इसमें कोड लोड करने का समय शामिल है, तो वास्तव में छोटा कोड निष्पादन समय से अधिक अंतर कर सकता है।