Προς το περιεχόμενο

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.

  • 0
afnman

C quiz ;p

Ερώτηση

Καλησπερα...

Εστω code σε C για console ενος μονοεπεξεργαστη ;p

Α->

>
int i;
for(i=0;i<40;i++)
{
if(i==10) do_this();
else if(i==20) do_that();
else something();
}

 

B->

>
int i;
for(i=0;i<10;i++)
{

something();
}
do_this();
for(i=11;i<20;i++)
{
something();
}
do_that();
for(i=21;i<40;i++)
{
something();
}

Aν μεταγλωττιστουν με εναν Microsoft compiler ,ποιος κωδικα θεωρειτε καλύτερο ή ειναι το ίδιο; Eγω λεω το Β λογω ταχυτητας αλλα δεν ειμαι σιγουρος 100%

Eξηγειστε γιατι. :P

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Προτεινόμενες αναρτήσεις

Με εντελώς στο περίπου νούμερα, απλά για το σκεπτικό:

1) Έστω ότι η cache χωράει 100 byte.

2) Η έκδοση με το loop είναι μικρότερη. Έστω ότι είναι 40 byte.

3) Η έκδοση χωρίς loop είναι μεγαλύτερη. Έστω ότι είναι 80 byte.

4) Έστω ότι η ίδια η something() είναι 50 byte.

 

> Στην πρώτη έκδοση βγαίνει 40 + 50 = 90 που είναι μικρότερο από 100, άρα χωράει όλη στην cache, ενώ η δεύτερη έκδοση 80 + 50 = 130 > 100 και προκαλούνται cache misses. Ένα cache miss κοστίζει πολύ, περισσότερο από το if/jmp ενός loop που υπάρχει ήδη στην cache.

 

Ξαναλέω ότι τα νούμερα δεν έχουν καμία σχέση με την πραγματικότητα, το σκεπτικό έγραψα.

 

Γενικά δηλαδή οι μικροί κώδικες, ακόμα κι αν έχουν cmp/jmp, μπορεί να είναι πιο γρήγοροι είτε λόγω cache, είτε λόγω cache-line, είτε λόγω paging κτλ.

 

Google για cache optimizations και θα βρεις μπόλικα papers.

 

@DirectX: άστα, μας έχει σπάσει τα νεύρα η VCL. Όντως μετά από ένα σωρό reports στο Quality Central συμπερίλαβε στις πρόσφατες εκδόσεις της κώδικα από τη fastcode, αλλά ακόμα συνεχίζει και συμπεριλαμβάνει δικές της assembly functions που είναι υλοποιημένες λάθος (όχι αργές, λάθος)!

Π.χ. ένα που έκλεισε πρόσφατα: http://qc.borland.com/wc/qcmain.aspx?d=22454

 

Για την ταχύτητα, δες π.χ. εδώ

http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_21982965.html

έναν διαγωνισμό που είχαμε κάνει για την ταχύτερη StringReplace. Παράδειγμα αποτελέσματος:

 

On my PC it had the following results on 1 Mb text:

Delphi StringReplace ~= 300 sec

Alkisg_StringReplace < 1 sec.

 

Για μεγαλύτερο string του Delphi χρειάζεται μέρες και δεν είχαμε την υπομονή να την περιμένουμε...

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Από ότι είδα στα γρήγορα, στην CodeGear Turbo C++ Explorer (δεν έχω πρόχειρη την MS-Visual C++) - φαίνεται πως ισοφαρίζουν, στο δικό μου υπολογιστή (Core Duo 1.60GHz).

 

Για το τεστ ζητώ από τον compiler, fastest possible code και Pentium Pro instruction set.

 

Επίσης έχω προσθέσει μια μικρή χρονο-καθυστέρηση σταθερή για κάθε ρουτίνα.

 

>
//---------------------------------------------------------------------------

#include <time.h>
#include <iostream>
#pragma hdrstop

#define	_DELAY	500

//---------------------------------------------------------------------------
void	do_this(void);
void	do_that(void);
void	something(void);
void	delay(int);

#pragma argsused
int main(int argc, char* argv[])
{
clock_t	ctBeginA,
		ctEndA,
		ctBeginB,
		ctEndB;
int i;			

ctBeginA = clock();
	for(i=0;i<40;i++)
	 {
		if(i==10) do_this();
			else if(i==20) do_that();
				else something();
	 }		
ctEndA = clock();

ctBeginB = clock();
	for(i=0;i<10;i++)
		something();
	do_this();
	for(i=11;i<20;i++)
		something();			
	do_that();
	for(i=21;i<40;i++)		
		something();
ctEndB = clock();

std::cout<<std::endl<<std::endl<<"A = "<<ctEndA-ctBeginA<<std::endl<<"B = "
		 <<ctEndB-ctBeginB<<std::endl<<std::endl<<"Press Enter to exit..";
std::cin.get();
return 0;
}
//---------------------------------------------------------------------------
void	do_this(void)
{
std::cout<<"do this";	
delay(_DELAY);
}
void	do_that(void)
{
std::cout<<"do that";
delay(_DELAY);	
}
void	something(void)
{
std::cout<<"something";
delay(_DELAY);	
}
void	delay(int nDelay)
{
clock_t	ctBegin = clock(),
		ctEnd;
do{
	ctEnd = clock();
	}while((ctEnd-ctBegin)<=nDelay);
}

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Φίλε μου, ο πρώτος κωδικας και ο δευτερος δεν κανουν το ιδιο πραγμα.

Ο πρώτοσ κωδικας θα εκτελεστει 40 φορες και ανάλογα την τιμή που θα έχει το ι θα μπαινει ι όχι στισ if .

 

o δευτερος θα εκτελεσει 10 φορες to something() meta θα βγει θα εκτελέσει το do_this();

kai μετα θα εκτελέσει αλλεσ 9 φορες το something () meta to do?that(); kai telos 19 φορες something():

 

ΔΕν μπορεις να συγκρινεις δυο διαφορετικουσ κωδικες

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Σωστός (και ωραίος αφού τους έσκισες και μάλιστα σε PASCAL! ;)) έχεις δίκιο, παρόλο που οι VCL ρουτίνες είναι πιο εύκολες στην χρήση τους σε σχέση με εκείνες της STL ή της ANSI-C, η ταχύτητα τους είναι κατώτερη των προσδοκιών, με ορισμένες εξαιρέσεις όπως η TList σε σχέση με την STL list όπου η πρώτη υπερτερεί (λίγα ms) προς την τελευταία (που είναι πιο περίπλοκη σε κώδικά) σε θέματα ταχύτητας εισαγωγής Nodes.

 

Όσον αφορά τα bugs.. το λάθος της WStrPos() είναι απαράδεκτο -δεν την τσέκαρε ποτέ κανένας άραγε;- :-(

 

Υ.Γ.

Καλύτερα πάντως να γράφανε optimized Delphi/PASCAL κώδικα πάρα 32-bit Assembly – καθώς όταν επικρατήσει η 64-bit αρχιτεκτονική θα πρέπει όλος αυτός ο κώδικας να γίνει εκ νέου port εκεί (Delphi 64bit – C/C++ Builder/Turbo C++ 64bit κτλ.)

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

> Aν μεταγλωττιστουν με εναν Microsoft compiler

 

Αυτό τώρα τι υποτίθεται ότι είναι, απαξιωτικό για τη Microsoft? Μακάρι και ο gcc να είχε το ίδιο καλό optimization...

 

Καλά βρε ποιος βάζει τέτοιες ασκήσεις;

 

Όπως ήταν αναμενόμενο και όπως έδειξαν οι δοκιμές, 2 παραπάνω if στο εσωτερικό ενός βρόχου είναι αμελητέα για σύγχρονες αρχιτεκτονικές, επειδή κάνουν πολύ καλές προβλέψεις για τα jump που έρχονται. Εξάλλου ο κώδικας είναι πολύ μικρός και πιθανώς να μην δημιουργούνται καν cache misses, όπως θα δημιουργούνταν σε ένα "κανονικό" πρόγραμμα - το οποίο και θα έβγαζε άχρηστες οποιεσδήποτε μετρήσεις (ένα cache miss κοστίζει πολύ περισσότερο από μερικές if).

 

Η ερώτηση νομίζω ότι πρέπει να απαντηθεί θεωρητικά, όχι πρακτικά. Π.χ. αν τρέξουμε τον παραπάνω κώδικα με Microsoft compiler σε επεξεργαστή 8086 είμαι σίγουρος ότι η διαφορά στην ταχύτητα εκτέλεσης θα είναι εμφανής. Το λέω με σιγουριά γιατί δεν πρόκειται κανείς να βρει 8086 για να με βγάλει λάθος! ;) Καλά πλάκα κάνω, απλά έχω φάει αμέτρητα χρόνια σε assembly optimization σε 8086 γι' αυτό το λέω.

 

Θεωρητικά, εφόσον στην Α περίπτωση έχεις 2 παραπανίσια if, το A είναι πιο αργό.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Υπό φυσιολογικές συνθήκες η delay οφείλει να διακόπτει το do{ }while() loop όταν συμπληρωθεί ο απαραίτητος χρόνος, αν υπάρχει δραστηριότητα της CPU, όπως συμβαίνει πάντα σε ένα multi-task περιβάλλον, μπορεί να υπάρξουν καθυστερήσεις στην ολοκλήρωση της (έστω και ελάχιστες -της τάξεως των msec), για αυτό και ο έλεγχος δεν είναι απόλυτος !=nDelay αλλά σχετικός <=nDelay.

 

Υπό αυτό το πρίσμα, η διαφορά που μου δίνεις δεν είναι σημαντική καθώς μπορεί να καταγράφει περιπτώσεις που η CPU απασχολείται με κάτι άλλο (κλείσε όλες τις εφαρμογές σου + συμβουλέψου τον Task Manager).

 

Για να δεις καλύτερα πόσο ασήμαντη είναι η διαφορά σε δευτερόλεπτα, άλλαξε τα ctEndA-ctBeginA και ctEndB-ctBeginB σε (ctEndA-ctBeginA)/CLK_TCK και (ctEndB-ctBeginB)/CLK_TCK αντίστοιχα -οπότε θα έχεις μια διαφορά των 31 msec καθώς και οι δυο ρουτίνες ολοκληρώνονται στα 20'', δηλαδή διαφορά .. αδιάφορη! (20",656 - 20",625 = 0,031) ;)

 

Υ.Γ.

Το CLK_TCK = 1000 σε CodeGear/Borland compilers.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Υποτίθεται ότι assembly γράφουν μόνο σε μερικές επιλεγμένες ρουτίνες, οπότε με ολόκληρο team που έχουν δε νομίζω να τους πάρει πάνω από μια βδομάδα να τις κάνουν port.

 

Εγώ πάντως αν ήμουν CEO της codegear (!!!) θα έδινα βάρος στον C builder, να ξαναγραφεί η VCL σε C++, να γίνει portable τουλάχιστον σε Win32/Linux/Mac OS και θα παράταγα τις βλακείες του .NET και του Delphi for php... Για .NET υπάρχουν πολύ καλύτερα περιβάλλοντα, ενώ για Visual Programming σε C μόνο τα MFC (sucks! - όχι portable), Qt και WxWidgets... Άνετα θα μπορούσε να σβήσει τον ανταγωνισμό η codegear.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Φυσικα ο κωδικας που θα φτιαξει ο compiler θα ειναι διαφορετικος αλλα τα αποτελεσματα ειναι παντα 100% τα ιδια.

 

Ουσιαστικα στο Β εχεις απαλειψει αποφασεις που θα μπορουσε να παρει ο υπολογιστης. Χωρις να γνωριζω και πολλα απο τεχνολογια compilers διαισθητικα θα ελεγα οτι το Β θα ειναι θεωρητικα πιο γρηγορο.

 

Πρακτικα, ο χρονος εκτελεσης των something(), do_this() kai do_that() παιζει τον πιο σημαντικο ρολο. Δεν νομιζω οτι μπορεις να εχεις μετρησιμα αποτελεσματα σε αποδοση χωρις να αλλαξεις τον κωδικα σε αυτα

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Ευχής έργο θα ήταν να σχεδίαζαν την VCL εξʼ αρχής σε C++ και φυσικά να την κάνανε Port σε άλλες πλατφόρμες (θα ήταν υπέροχο!), αλλά (πάντα υπάρχει ένα αλλά..) δυστυχώς όπως έχω αναφέρει σε παλαιότερο topic, για την Borland ο C/C++ Builder ήταν πάντα αποπαίδι, σε τέτοιο βαθμό που κόντεψε να τον σκοτώσει εντελώς.

Η τελευταία έκδοση C++ Builder για πολλά χρόνια ήταν κολλημένη στην 6.0 του 2002 με 4 διαθέσιμα upgrades της ίδιας περίπου εποχής.

 

Ευτυχώς από πέρσι η CodeGear ξεκίνησε την ενεργότερη υποστήριξη του, κυκλοφορώντας αρχικά το νέο C++ personality ως μέρος (στην αρχή ανεξάρτητο plugin-download) του BDS 2006 και ύστερα ως αυθύπαρκτο προϊόν (C/C++ Builder 2006, Turbo C++) πράγμα που συνεχίσθηκε και φέτος (C/C++ Builder 2007).

 

Παράλληλα φαίνεται ότι μαζεύουν κόσμο που ασχολείται σοβαρά με την C/C++ όπως ο νέος Product Manager του C/C++ Builder project ο οποίος είναι μέλος του ISO/BSI/ANSI C++ committee: http://blogs.codegear.com/nickhodges/2007/09/13/38936 & http://www.codegear.com/el/article/37129

 

Ελπίζω να βγει κάτι καλό από αυτό καθώς είναι ένα προϊόν που το αξίζει πραγματικά καλύτερη τύχη..

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Eτρεξα το prog sou σε Visual studio.NET xωρις κανενα optimization και Intel duo core 1.66

A= 20656

B= 20625

 

Μια ερώτηση...η time είναι ξεχωριστο thread του προγράμματος και διακοπτεται κανονικά απο άλλες διεργασιες σωστά;Εννοω οτι μετραει μονο αυτο το προγραμμα και οχι τυχον άλλες διακοπες.

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Και για την απολυτη ταχυτητα

 

>

something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
do_this();
something();
something();
something();
something();
something();
something();
something();
something();
something();
do_that();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();
something();

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Πρακτικα, ο χρονος εκτελεσης των something(), do_this() kai do_that() παιζει τον πιο σημαντικο ρολο. Δεν νομιζω οτι μπορεις να εχεις μετρησιμα αποτελεσματα σε αποδοση χωρις να αλλαξεις τον κωδικα σε αυτα

 

Aντικατεστησε τα something(),do_this() και do_that() με cout << "something",cout << "do_this",cout << "do_that" αντιστοιχα

 

Φίλε μου, ο πρώτος κωδικας και ο δευτερος δεν κανουν το ιδιο πραγμα.

Ο πρώτοσ κωδικας θα εκτελεστει 40 φορες και ανάλογα την τιμή που θα έχει το ι θα μπαινει ι όχι στισ if .

 

o δευτερος θα εκτελεσει 10 φορες to something() meta θα βγει θα εκτελέσει το do_this();

kai μετα θα εκτελέσει αλλεσ 9 φορες το something () meta to do?that(); kai telos 19 φορες something():

 

ΔΕν μπορεις να συγκρινεις δυο διαφορετικουσ κωδικες

στον Α:

απο 0 εως και 9 ( συνολο 10 φορες) εκτελειτε tο something()

στην 10η φορα εκτελειτε το do_this()

απο την 11η φορα μεχρι και την 19η φορα εκτελειτε το something() (σύνολο 9 φορες)

την 20 φορά εκτελείται do_that

απο την 21 εως και την 39 φορά εκτελειτε το something()

(συνολο 19 φορές)

..its the same shit...

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες

Believe it or not στους καινούργιους επεξεργαστές αυτό είναι πιο αργό λόγω cache & pipelining... :)

 

Όποιος έχει όρεξη να δει υπερ-optimized κώδικα Delphi & Assembly ας φέρει μια βόλτα στο http://fastcode.sourceforge.net/

Μιλάμε για χιλιάδες φορές μεγαλύτερη ταχύτητα από τις αντίστοιχες συναρτήσεις της VCL..

Κοινοποιήστε αυτήν την ανάρτηση


Σύνδεσμος στην ανάρτηση
Κοινοποίηση σε άλλες σελίδες
×
×
  • Δημιουργία νέου...