Google Groupes n'accepte plus les nouveaux posts ni abonnements Usenet. Les contenus de l'historique resteront visibles.

Optimisation de la division par 2

8 vues
Accéder directement au premier message non lu

candide

non lue,
29 oct. 2009, 18:14:1029/10/2009
à
Bonjour,

Diff�rentes lectures m'avaient fait admettre que le reste d'un entier
modulo 2 ie (x % 2) produisait un code �quivalent � sa version bit � bit
ie (x & 1).

Avec gcc sous Ubuntu, et si l'option d'optimisation O2 est allum�e, les
temps d'ex�cution sont quasi identiques. Sans option d'optimisation, la
version modulo est 30% moins rapide que la version bit � bit.

Par contre, sous Windows XP et avec MS Visual Express + options
d'optimisation activ�es, j'obtiens un �cart significatif. Ci-dessous, le
code et l'affichage obtenu. Ces �carts m'ont �t� confirm�s par d'autres
utilisateurs. Qu'en pensez-vous ?

/* ======================================= */
#include <stdio.h>
#include <time.h>

int est_pair0(int n)
{
return !(n & 0x1);
}

int est_pair1(int n)
{
return !(n % 2);
}

double test(unsigned int n, int (*f) (int))
{
unsigned int i, j;
int s = 0;
clock_t now = clock();

for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
s += f(i * j);
printf("%d\n", s);
return (double) (clock() - now) / CLOCKS_PER_SEC;

}

#define N (unsigned int)10000
#define NB_TESTS 10
int main(void)
{
int i,j;
int (*f[2])(int)={est_pair0, est_pair1};

for (j=0;j<2;j++)
{
double duree=0;
for (i=0;i<NB_TESTS;i++)
duree+=test(N, f[j]);

printf("estpair%d : %.2lf secondes\n\n", j, duree/NB_TESTS);
}

return 0;
}
/* ======================================= */

75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
estpair0 : 1.03 secondes

75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
estpair1 : 1.42 secondes

Vincent Lefevre

non lue,
30 oct. 2009, 13:13:4330/10/2009
à
Dans l'article <4aea13b3$0$8005$426a...@news.free.fr>,
candide <can...@free.invalid> �crit:

> int est_pair0(int n)
> {
> return !(n & 0x1);
> }

> int est_pair1(int n)
> {
> return !(n % 2);
> }

Et que donne ceci?

int est_pair2(int n)
{
return !((unsigned int) n % 2);
}

Tous les compilateurs ne d�tectent peut-�tre pas que le signe du "%"
n'aura aucune influence � cause du "!".

--
Vincent Lef�vre <vin...@vinc17.net> - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / Ar�naire project (LIP, ENS-Lyon)

candide

non lue,
30 oct. 2009, 15:57:2730/10/2009
à
Vincent Lefevre a �crit :

>
> Et que donne ceci?
>
> int est_pair2(int n)
> {
> return !((unsigned int) n % 2);
> }
>


Ah ! bien vu, les temps deviennent identiques :


75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000

estpair0 : 0.91 secondes

75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000

estpair1 : 1.35 secondes

75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000
75000000

estpair2 : 0.91 secondes


Merci.

candide

non lue,
30 oct. 2009, 18:16:3230/10/2009
à
Vincent Lefevre a �crit :

> Tous les compilateurs ne d�tectent peut-�tre pas que le signe du "%"
> n'aura aucune influence � cause du "!".
>


En r�alit�, je ne pense pas que ce soit l'explication ultime puisque si
je supprime des return des trois fonctions la pr�sence du symbole "!" de
n�gation, les �carts restent dans le m�me sens. Je pense en fait que,
tout simplement, si le compilateur est s�r et certain que l'on effectue
une division entre entiers d'un type non sign� (� cause de la conversion
que tu sugg�res et des r�gles de conversion), il tente une division par
d�calage de bits (j'ai v�rifi� que cela marchait aussi pour des
puissances de 2 et pas seulement 2). D'ailleurs, si on �crit plut�t :

int est_pair2(int n)
{
return (n % 2U);

}

le temps est le m�me que si on faisait n & 1 ou (unsigned int) n % 2.

Samuel Devulder

non lue,
31 oct. 2009, 03:23:1931/10/2009
à
candide a ïŋ―crit :
> Vincent Lefevre a ïŋ―crit :
>
>> Tous les compilateurs ne dïŋ―tectent peut-ïŋ―tre pas que le signe du "%"
>> n'aura aucune influence ïŋ― cause du "!".
>>
>
>
> En rïŋ―alitïŋ―, je ne pense pas que ce soit l'explication ultime puisque si
> je supprime des return des trois fonctions la prïŋ―sence du symbole "!" de
> nïŋ―gation, les ïŋ―carts restent dans le mïŋ―me sens. Je pense en fait que,
> tout simplement, si le compilateur est sïŋ―r et certain que l'on effectue
> une division entre entiers d'un type non signïŋ― (ïŋ― cause de la conversion
> que tu suggïŋ―res et des rïŋ―gles de conversion), il tente une division par
> dïŋ―calage de bits (j'ai vïŋ―rifiïŋ― que cela marchait aussi pour des
> puissances de 2 et pas seulement 2). D'ailleurs, si on ïŋ―crit plutïŋ―t :

>
> int est_pair2(int n)
> {
> return (n % 2U);
>
> }
>
> le temps est le mïŋ―me que si on faisait n & 1 ou (unsigned int) n % 2.

Il suffit de jetter un oeil au code ASM.

int f0(int n) {
return n%2;
}
_f0:
movl 4(%esp), %eax
movl %eax, %ecx
shrl $31, %ecx
leal (%eax,%ecx), %edx
andl $-2, %edx
subl %edx, %eax
ret

int f1(int n) {
return n & 1;
}
_f1:
movl 4(%esp), %eax
andl $1, %eax
ret

int f2(unsigned int n) {
return n%2;
}
_f2:
movl 4(%esp), %eax
andl $1, %eax
ret

int f3(unsigned int n) {
return n & 1;
}
_f3:
movl 4(%esp), %eax
andl $1, %eax
ret

Bref, on voit que dans le cas int non signïŋ― le compilo utilise des
bitmasks et les code ASM sont strictement identiques.

En revanche pour les versions signïŋ―es, le code est plus lourd. En effet
comme (-1) & 1 donne 1 et que (-1) % 2 donne -1, le code asm calcule n %
2 ainsi: n - ((n + (n>>31) & -2)

sam.

-ed-

non lue,
31 oct. 2009, 04:13:1431/10/2009
à
On 29 oct, 23:14, candide <cand...@free.invalid> wrote:
>         printf("estpair%d : %.2lf secondes\n\n",  j, duree/NB_TESTS);

N'existe pas. C'est

printf("estpair%d : %.2f secondes\n\n", j, duree/NB_TESTS);

-ed-

non lue,
31 oct. 2009, 04:15:0131/10/2009
à
On 29 oct, 23:14, candide <cand...@free.invalid> wrote:

> #define N (unsigned int)10000

Une façon compliqué et erronée

#define N ((unsigned int)10000)

d'écrire

#define N 10000U


Pierre Maurette

non lue,
31 oct. 2009, 04:39:5331/10/2009
à
candide, le 29/10/2009 a ï¿œcrit :
> Bonjour,

[...]

Bonjour,

Vous ne chronomï¿œtrez pas les instructions que vous voulez tester, ou
disons que vous les chronomï¿œtrez noyï¿œes dans le bruit. Votre programme
passe tout son temps dans les appels de fonctions, dans une moindre
mesure dans les printf(), et quelsues autres trucs.
Le fait de passer un pointeur sur fonction en argument empï¿œche
l'inlining. Je vous suggï¿œre les manips suivantes, l'une aprï¿œs l'autre
ou en mï¿œme temps:

- dans vos fonctions est_pairx(), mettre juste
return 0;
Si ï¿œa se trouve ce sera plus long ;-)

- virer le printf() dans test().

- remplacer le f(i * j) dans test() par l'une ou l'autre de vos
instructions.

- Alternativement, ï¿œcrire une:
static int est_pair(int n) // ou static inline etc.
{
return !(n % 2);
}
et l'appeler directement dans test().

Puisque vous ï¿œtes sur l'optimisation, voyez le f(i*j) en fond de
boucle. ï¿œa peut ï¿œtre coï¿œteux et bien plus long (le bruit le bruit) que
votre instruction ᅵ tester, si le compilateur ne constate pas ᅵ votre
place que cette multiplication de deux valeurs non constantes n'est en
fait qu'un incrï¿œment.


--
Pierre Maurette


-ed-

non lue,
31 oct. 2009, 04:50:2731/10/2009
à
On 30 oct, 18:13, Vincent Lefevre <vincent+n...@vinc17.org> wrote:
> Dans l'article <4aea13b3$0$8005$426a7...@news.free.fr>,
>   candide <cand...@free.invalid> écrit:

>
> > int est_pair0(int n)
> > {
> >     return !(n & 0x1);
> > }
> > int est_pair1(int n)
> > {
> >     return !(n % 2);
> > }
>
> Et que donne ceci?
>
> int est_pair2(int n)
> {
>     return !((unsigned int) n % 2);
>
> }
>
> Tous les compilateurs ne détectent peut-être pas que le signe du "%"
> n'aura aucune influence à cause du "!".

Bien vu :

est_pair0() : 0.45 secondes

est_pair1() : 0.47 secondes

est_pair2() : 0.42 secondes


Process returned 0 (0x0) execution time : 13.510 s
Press any key to continue.

Sous Vista avec Code::Blocks.

avec ce code :

/* ======================================= */
#include <stdio.h>
#include <time.h>

typedef int (fun_f) (int);

static int est_pair0 (int n)
{
return !(n & 1);
}

static int est_pair1 (int n)
{
return !(n % 2);
}

int est_pair2(int n)


{
return !((unsigned int) n % 2);

}

/* retourne la durée du test en ms */
static double test (unsigned int n, fun_f *f)


{
unsigned int i, j;
int s = 0;

clock_t start = clock ();
double ms;

for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
s += f (i * j);
}
}

ms = (clock () - start) * 1000 / (double) CLOCKS_PER_SEC;
#if 0
printf ("%d/%ld\n", s, (long) n*n);
#endif
return ms;
}

#define N 10000
#define NB_TESTS 10
#define NB_ELEM(a) (sizeof(a)/sizeof*(a))

int main (void)
{
size_t i;
fun_f *af[] =
{
est_pair0, est_pair1, est_pair2};

for (i = 0; i < NB_ELEM(af); i++)
{
unsigned long duree = 0;
int j;
for (j = 0; j < NB_TESTS; j++)
duree += test (N, af[i]);

printf ("est_pair%d() : %.2f secondes\n\n", i, (double) duree /
(NB_TESTS * 1000));
}

return 0;
}

-ed-

non lue,
31 oct. 2009, 04:52:2331/10/2009
à
On 31 oct, 08:23, Samuel Devulder <samuel-dot-devul...@geensys.com>
wrote:

> Il suffit de jetter un oeil au code ASM.

Ce qui donne une explication pour une implémentation donnée, dans des
conditions données ...

Éric Lévénez

non lue,
31 oct. 2009, 07:53:0731/10/2009
à
-ed- a �crit :

Non. "%lf" est tout � fait valide, m�me s'il est plus courant d'�crire "%f".

--
�ric L�v�nez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>

Samuel Devulder

non lue,
31 oct. 2009, 09:32:1531/10/2009
à
candide a �crit :

> Bonjour,
>
> Diff�rentes lectures m'avaient fait admettre que le reste d'un entier
> modulo 2 ie (x % 2) produisait un code �quivalent � sa version bit � bit
> ie (x & 1).

En fait c'est faux si x est sign�.

(x % 2) en version sign�e est traduite comme
x - ((x + (((unsigned)x)>>31)) & ~1)
(en assumant du 32bit).

L'id�e est ici de soustraire � x tout sauf son bit de poids faible tout
en soustrayant 2 si x est impair n�gatif. Ainsi on a bien les valeurs 0,
1 et -1 dispo. C'est vraiment un codage compact du calcul.

> int est_pair1(int n)
> {
> return !(n % 2);
> }

Ici quand je regarde les code ASM de GCC et de VS, on a pas du tout la
m�me chose.

GCC:
xorl %eax, %eax
testb $1, 4(%esp)
sete %al
ret
(C'est grosso modo un "and" ce truc). GCC ne se pr�occupe pas trop du
signe de n % 2 et fait quelque chose de sioux.

VC (98):
and eax, -2147483647
jns SHORT $L105
dec eax
or eax, -2
inc eax
$L105:
neg eax
sbb eax, eax
inc eax
ret 0

Le "and" du d�but effectue le test n<0 tout en pr�servant le bit de
poids faible (+/- sioux). S'en suivent des calculs revenant � calculer 0
si le bit de poids faible est 0, et -1 sinon.

En fait la partie jusqu'� L105 est un calcul effectif de (n % 2) tenant
compte du signe. La partie finale apr�s L105 calcule une inversion 0->1,
!0 ->0.

Donc VC effectue assez peu d'optim, il calcule (n % 2) puis le "not" du
r�sultat du modulo. En fait ce calcul du modulo fait par VC est une
version sans d�calage, mais avec saut. Cela peut �tre int�ressant
suivant le type de CPU.

Cela dit, quoi qu'il en soit GCC s'en sort haut la main car il a compris
qu'on se fiche de calculer exactement (n%2) et se contente d'un test sur
le bit de poids faible de n directement. C'est d'ailleurs le code que
fait VC98 sur les unsigned:
mov eax, DWORD PTR _n$[esp-4]
not eax
and eax, 1

La morale est qu'il vaut mieux clairement utiliser des unsigned pour les
manip bit-�-bits car "d'une fa�on g�n�rale", les compilos semblent �tre
mieux capables de mener les optims jusqu'au bout et produire un code asm
performant.

sam.

candide

non lue,
31 oct. 2009, 09:53:1931/10/2009
à
Pierre Maurette a �crit :

>
> Vous ne chronom�trez pas les instructions que vous voulez tester, ou
> disons que vous les chronom�trez noy�es dans le bruit. Votre programme


> passe tout son temps dans les appels de fonctions, dans une moindre
> mesure dans les printf(), et quelsues autres trucs.

Certes, il y a du bruit mais je ne crois pas que ce soit g�nant pour
discriminer puisque tous les tests font le m�me bruit. Disons que �a va
juste changer les proportions de lenteur.

> - dans vos fonctions est_pairx(), mettre juste
> return 0;

> Si �a se trouve ce sera plus long ;-)


Pas compris.

>
> - virer le printf() dans test().


Il est bien pratique pour v�rifier la conformit� entre les tests mais on
peut r�duire les affichages.


>
> - remplacer le f(i * j) dans test() par l'une ou l'autre de vos
> instructions.


Oui mais il faut bien que je fasse quelque chose d'utile (sinon les
optimisations peuvent ignorer les calculs) et d'assez long pour que ce
soit significatif.

>
> - Alternativement, �crire une:


> static int est_pair(int n) // ou static inline etc.
> {
> return !(n % 2);
> }
> et l'appeler directement dans test().
>

Jamais bien compris cet histoire de inlining mais de toute fa�on, la
question ne va plus se poser puisque je vais r��crire les tests sans
appel de fonctions.

> Puisque vous �tes sur l'optimisation, voyez le f(i*j) en fond de boucle.
> �a peut �tre co�teux et bien plus long (le bruit le bruit) que votre

Vous proposez quoi � la place car je n'ai pas beaucoup d'imagination ?

> instruction � tester, si le compilateur ne constate pas � votre place


> que cette multiplication de deux valeurs non constantes n'est en fait

> qu'un incr�ment.
>
>


Comprends pas.

Bon, j'ai refait des tests en respectant ce que j'ai compris vos
propositions

Les r�sultats confirment :
-- qu'il y avait du bruit
-- que la tendance du premier test est conserv�e :
*) �galit� pour gcc,
*) �cart encore plus flagrant pour Visual.

Voici les temps pour les m�mes valeurs que dans la premi�re batterie de
tests (avec optimisation pour les deux compilateurs) :
-----------------------------------
gcc sous Ubuntu
75000000
Temps CPU : 0.21 seconde.

75000000
Temps CPU : 0.21 seconde.

75000000
Temps CPU : 0.22 seconde.
-----------------------------------
Visual
75000000
Temps CPU : 0.13 seconde.

75000000
Temps CPU : 0.72 seconde.

75000000
Temps CPU : 0.14 seconde.
-----------------------------------

Voici le code, j'ai un �crit une bonne vieille macro illisible mais
c'est quand m�me plus simple pour faire �voluer des codes homog�nes
entre les trois tests :


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

#define f0(n) (!((n) & 0x1))
#define f1(n) (!((n) % 2))
#define f2(n) (!((n) % 2U))

#define N 10000
#define NB_TESTS 10

#define TEST(f) {int nt = NB_TESTS;\
clock_t now = clock();\
unsigned s = 0;\
for (nt = 0; nt < NB_TESTS; nt++)\
{\
int i, j = 0;\
s = 0;\
\
for (i = 0; i < N; i++)\
for (j = 0; j < N; j++)\
s += (unsigned)f(i * j);\
}\
printf("%u\n", s);\
printf("Temps CPU : %.2f seconde.\n\n",\
(double) (clock() - now) / CLOCKS_PER_SEC / NB_TESTS);\
}

int main(void)
{
TEST(f0)
TEST(f1)
TEST(f2)

return 0;
}

candide

non lue,
31 oct. 2009, 09:57:0831/10/2009
à
Samuel Devulder a �crit :

> (x % 2) en version sign�e est traduite comme
> x - ((x + (((unsigned)x)>>31)) & ~1)
> (en assumant du 32bit).
>


Ah ! OK donc, ce n'est quand m�me pas une brute division.

> Donc VC effectue assez peu d'optim, il calcule (n % 2) puis le "not" du
> r�sultat du modulo. En fait ce calcul du modulo fait par VC est une
> version sans d�calage, mais avec saut. Cela peut �tre int�ressant
> suivant le type de CPU.

Pas tout compris car connais pas l'assembleur.


> La morale est qu'il vaut mieux clairement utiliser des unsigned pour les
> manip bit-�-bits car "d'une fa�on g�n�rale", les compilos semblent �tre
> mieux capables de mener les optims jusqu'au bout et produire un code asm
> performant.


Ah ! c'est ce notre -ed- nous a toujours dit et je crois qu'il a raison ;)


>
> sam.

sam <--> asm

un nom pr�destin� quoi !!

candide

non lue,
31 oct. 2009, 10:00:0931/10/2009
à
-ed- a �crit :

> unsigned int i, j;
> int s = 0;
> clock_t start = clock ();
> double ms;
>
> for (i = 0; i < n; i++)
> {
> for (j = 0; j < n; j++)
> {
> s += f (i * j);
>

J(avais pas fait gaffe mais il y a un risque d'overflow donc il vaudrait
mieux caster en unsigned ce que j'ai rectifi� dans mes derniers tests,
cf. r�ponse � Pierre Maurette

candide

non lue,
31 oct. 2009, 10:01:4631/10/2009
à
-ed- a �crit :

> On 29 oct, 23:14, candide <cand...@free.invalid> wrote:
>
>> #define N (unsigned int)10000
>
> Une fa�on compliqu� et erron�e
>

Pourquoi erron�e ?

> #define N ((unsigned int)10000)
>
> d'�crire
>
> #define N 10000U
>
>


Exact.

Je suis un programmeur du dimanche ;)

candide

non lue,
31 oct. 2009, 10:18:1331/10/2009
à
-ed- a �crit :

> On 29 oct, 23:14, candide <cand...@free.invalid> wrote:
>> printf("estpair%d : %.2lf secondes\n\n", j, duree/NB_TESTS);
>
> N'existe pas.


Ah bon %lf pour printf() n'existe pas ?


> C'est
>
> printf("estpair%d : %.2f secondes\n\n", j, duree/NB_TESTS);


Exact. Et si j'en crois la Norme, ce que j'ai �crit serait m�me un UB.


A ma d�charge, j'ai recopi� ce type de code en 2005 (l'ann�e o� j'ai
commenc� le C) sur un forum usenet (je sais plus lequel) car j'avais
besoin de timer du code. J'ai r�utilis� ce code sans changement et j'ai
sans doute eu tort.


Mais je tiens quand m�me � pr�ciser qu'alors que ce besoin est tr�s
courant, les docs ne donnent pas d'information sur cette question. Ma
version de la faq fclc ne dit rien (� propos, je signale � �ric L�v�nez
qu'il serait bien qu'on puisse t�l�charger la faq au format texte, c'est
quand m�me plus pratique pour y faire des recherches de passer par Google).

La faq clc cite certes clock() mais n'en parle pas pour timer du code
et ne donne aucun exemple.

Et ton site, il dit quelque chose � ce sujet ?

Par contre, je viens de voir que tu donnes un exemple dans la FAQ de
developpez.

Samuel Devulder

non lue,
31 oct. 2009, 10:48:2931/10/2009
à
candide a �crit :

> Samuel Devulder a �crit :
>
>> (x % 2) en version sign�e est traduite comme
>> x - ((x + (((unsigned)x)>>31)) & ~1)
>> (en assumant du 32bit).
>>
>
>
> Ah ! OK donc, ce n'est quand m�me pas une brute division.

Oui parce qu'on est dans une puissance de 2.

>> Donc VC effectue assez peu d'optim, il calcule (n % 2) puis le "not" du
>> r�sultat du modulo. En fait ce calcul du modulo fait par VC est une
>> version sans d�calage, mais avec saut. Cela peut �tre int�ressant
>> suivant le type de CPU.
>
> Pas tout compris car connais pas l'assembleur.

En �quivalent C il calcule le modulo sign� ainsi pour une puissance de 2
(cod�e dans MASK):

#define MASK 0x00000001 /* de la forme (1<<k)-1 */

n &= 0x80000000 | MASK;
if(n<0) n = ((n-1) | ~MASK) + 1;

Ce pattern doit marcher avec n'importe quel MASK du type (1<<k) - 1.

De son cot� le calcul du modulo "une puissance de 2" sign� par GCC est
dans le genre ci:

if(n<0) n += MASK;
n = n - (n & ~MASK);

Les deux impl�mentation diff�rent dans le sens de celle de VC n�cessite
moins de registres que celle de GCC. En effet n-1 se calcule directement
alors que "n - (un truc d�pendant de n)" n�cessite de sauvegarder n
dans un registre temporaire ou sur la pile.

> sam <--> asm
>
> un nom pr�destin� quoi !!

Il y a de l'id�e en effet.

sam.

Pierre Maurette

non lue,
31 oct. 2009, 12:07:0431/10/2009
à
candide, le 31/10/2009 a ï¿œcrit :
> Pierre Maurette a ï¿œcrit :
>
>>
>> Vous ne chronomï¿œtrez pas les instructions que vous voulez tester, ou
>> disons que vous les chronomï¿œtrez noyï¿œes dans le bruit. Votre programme

>> passe tout son temps dans les appels de fonctions, dans une moindre
>> mesure dans les printf(), et quelsues autres trucs.
>
> Certes, il y a du bruit mais je ne crois pas que ce soit gï¿œnant pour
> discriminer puisque tous les tests font le mï¿œme bruit.

Une caractï¿œrisque premiï¿œre du bruit est d'ï¿œtre alï¿œatoire. Donc l'idï¿œe
de "mï¿œme bruit" n'a pas de sens.

> Disons que ï¿œa va


> juste changer les proportions de lenteur.

???

>> - dans vos fonctions est_pairx(), mettre juste
>> return 0;

>> Si ï¿œa se trouve ce sera plus long ;-)
>
>
> Pas compris.

Tu m'ï¿œtonnes, John. Si:

int est_pair0(int n)
{
return !(n & 0x1);
}

vous remplacez par:

int est_pair0(int n)
{
return 0;
}

chez moi c'est un peu plus long. Ce qui pourrait vous convaincre que
vous ne mesurez que du bruit.

>> - virer le printf() dans test().
>
>

> Il est bien pratique pour vᅵrifier la conformitᅵ entre les tests mais on
> peut rï¿œduire les affichages.

Bien entendu. Le problï¿œme c'est que vous le placez avant la prise de
date. Il est trï¿œs facile de contourner ce problï¿œme. CF Ed


>> - remplacer le f(i * j) dans test() par l'une ou l'autre de vos
>> instructions.
>
>
> Oui mais il faut bien que je fasse quelque chose d'utile (sinon les
> optimisations peuvent ignorer les calculs) et d'assez long pour que ce
> soit significatif.

Bien entendu, il faut vᅵrifier. Si ᅵa ne marche pas, ne pas hᅵsiter ᅵ
utiliser /volatil/.

>> - Alternativement, ï¿œcrire une:


>> static int est_pair(int n) // ou static inline etc.
>> {
>> return !(n % 2);
>> }
>> et l'appeler directement dans test().
>>
>
> Jamais bien compris cet histoire de inlining

C'est quand mᅵme fondamental. Vous mesurez en rᅵalitᅵ des appels
lourds, avec tout le bordel dans la pile et la pile de fonctions.

> mais de toute faï¿œon, la
> question ne va plus se poser puisque je vais rᅵᅵcrire les tests sans
> appel de fonctions.

J'ai des doutes.

>> Puisque vous ï¿œtes sur l'optimisation, voyez le f(i*j) en fond de boucle.
>> ï¿œa peut ï¿œtre coï¿œteux et bien plus long (le bruit le bruit) que votre
>
> Vous proposez quoi ᅵ la place car je n'ai pas beaucoup d'imagination ?

ᅵa c'est du B-A-BA de la programmation. Bien entendu ᅵ chaque turn du
fond de boucle, vous n'avez pas besoin de faire f(i*j) mais f(k) avec k
+= i)

>> instruction ᅵ tester, si le compilateur ne constate pas ᅵ votre place


>> que cette multiplication de deux valeurs non constantes n'est en fait

>> qu'un incrï¿œment.

> Comprends pas.

Vous m'ï¿œtonnez. CF plus haut. Rassurez-moi: vous ï¿œtes dans l'Education
Nationale ?

--
Pierre Maurette


Pierre Maurette

non lue,
31 oct. 2009, 12:58:1131/10/2009
à
Samuel Devulder, le 31/10/2009 a ï¿œcrit :

[...]

> En fait c'est faux si x est signᅵ.

Vous parlez d'assembleur. En fait la diffï¿œrence, c'est...
C'est un peu compliquᅵ ᅵ expliquer.

Peut-ᅵtre pas si compliquᅵ que ᅵa...

Ce que je veux dire, c'est qu'en C, les variables sont signï¿œes, et ï¿œa
fout un grosse merde. En assembleur, ce sont les opï¿œrateurs qui sont -
ou non - signï¿œs, et c'est bien plus simple.

--
Pierre Maurette


Samuel Devulder

non lue,
31 oct. 2009, 14:06:1831/10/2009
à
Pierre Maurette a ï¿œcrit :
> Samuel Devulder, le 31/10/2009 a ï¿œcrit :
>
> [...]
>
>> En fait c'est faux si x est signᅵ.
>
> Vous parlez d'assembleur. En fait la diffï¿œrence, c'est...
> C'est un peu compliquᅵ ᅵ expliquer.

Bah de toute faï¿œon pour comprendre pourquoi tel ou tel code C a priori
ᅵquivalents ne marchent pas ᅵ la mᅵme vitesse, une bonne faᅵon de
comprendre est de jeter un oeil au code ASM.

Pas besoin de tout savoir lire, on identifie assez vite les accï¿œs
mï¿œmoire, les sauts et les registres et le goulet d'ï¿œtranglement saute au
yeux, mais pas toujours. Par exemple la recherche du min/max de la
semaine derniᅵre, car lᅵ c'ᅵtait en deᅵᅵ de l'ASM que la diffᅵrence
d'algo se produit (prï¿œdiction de sauts dans le CPU).

>
> Peut-ᅵtre pas si compliquᅵ que ᅵa...
>
> Ce que je veux dire, c'est qu'en C, les variables sont signï¿œes, et ï¿œa
> fout un grosse merde. En assembleur, ce sont les opï¿œrateurs qui sont -
> ou non - signï¿œs, et c'est bien plus simple.

Oui, tu veux dire qu'en ASM on doit savoir ce que l'on fait. Ca devrait
ï¿œtre partout la mï¿œme chose non? En fait le soucis est que l'on ne pense
pas naturellement en complᅵment ᅵ 2. Je suis persuadᅵ que beaucoup, si
ce n'est tous pensent intuitivement "positif" ou ï¿œventuellement avec un
bit de signe sᅵparᅵ du reste comme dans les float IEEE (donc 2 valeurs
de zᅵro). Cela n'aide pas ᅵ ᅵcrire des expressions valides
indï¿œpendamment du signe.

Du coup (x%16) devenant (x&15) marche bien pour les positifs et se casse
la figure pour les nï¿œgatifs. Avec une reprï¿œsentation snnnnnnn (ie bit de
signe sᅵparᅵ) ᅵa serait plus simple, on ᅵcrirait (x & 0b10001111) (abus
de notation avec le 0bnnnnn, mais il manque une faï¿œon simple de
reprï¿œsenter les nombres binaires en C de toute faï¿œon, donc j'emprunte au
vhdl pour l'occasion). Mais bon on est contraint au complᅵment ᅵ 2, il
faut faire avec elle et ses piï¿œges.

D'ailleurs la reprᅵsentation en complᅵment ᅵ 2 est assez dangereuse dans
le sens ou elle est "asymï¿œtrique". La valeur minimale est son propre
inverse (sommᅵe ᅵ elle mᅵme elle le rᅵsultat vaut zᅵro), donc on ne peut
assumer que l'opposᅵ d'un nombre nᅵgatif est toujours positif. C'est
assez troublant, et fait que par exemple que le code suivant est non
fiable malgrᅵ les gardes-fous:

#define SIZE 10
int tab[SIZE];

int get_tab(int n) {
if(n<0) n = -n;
if(n>=SIZE) n = SIZE-1;
return tab[n];
}

en effet get_tab(INT_MIN) dï¿œborde le tableau par le bas car le garde-fou
ᅵ n<0 ne change pas le signe de n quand n=INT_MIN.

sam.

Vincent Lefevre

non lue,
31 oct. 2009, 16:48:1531/10/2009
à
Dans l'article <4aeb65c0$0$32749$426a...@news.free.fr>,
candide <can...@free.invalid> �crit:

> Vincent Lefevre a �crit :

> > Tous les compilateurs ne d�tectent peut-�tre pas que le signe du "%"
> > n'aura aucune influence � cause du "!".

> En r�alit�, je ne pense pas que ce soit l'explication ultime puisque si
> je supprime des return des trois fonctions la pr�sence du symbole "!" de
> n�gation, les �carts restent dans le m�me sens.

Mon explication n'est valable que lorsqu'il y a un "!". Si tu
supprimes le "!", c'est normal que tu obtiennes des temps diff�rents
(le compilateur ne pouvant pas optimiser la version % sign�e puisque
cela donnerait un r�sultat diff�rent). En revanche, s'il y a un "!",
les compilateurs les plus avanc�s vont �tre capables d'optimiser la
version sign�e puisque !(-1) == !1; mais d'autres compilateurs n'en
sont pas capables et g�n�rent du code non optimis�, comme s'il n'y
avait pas de "!". Donc mieux vaut utiliser la version non sign�e avec
"!" (ou bien le "&"), m�me si la version sign�e est s�mantiquement
�quivalente.

> Je pense en fait que, tout simplement, si le compilateur est s�r et
> certain que l'on effectue une division entre entiers d'un type non
> sign� (� cause de la conversion que tu sugg�res et des r�gles de
> conversion), il tente une division par d�calage de bits (j'ai
> v�rifi� que cela marchait aussi pour des puissances de 2 et pas
> seulement 2). D'ailleurs, si on �crit plut�t :

> int est_pair2(int n)
> {
> return (n % 2U);
> }

> le temps est le m�me que si on faisait n & 1 ou (unsigned int) n % 2.

Oui, car n % 2U est une version non sign�e du modulo.

Vincent Lefevre

non lue,
31 oct. 2009, 17:00:2931/10/2009
à
Dans l'article <4aec7ca8$0$29451$426a...@news.free.fr>,
Samuel Devulder <samuel-do...@geensys.com> �crit:

> D'ailleurs la repr�sentation en compl�ment � 2 est assez dangereuse dans
> le sens ou elle est "asym�trique". La valeur minimale est son propre
> inverse (somm�e � elle m�me elle le r�sultat vaut z�ro), donc on ne peut
> assumer que l'oppos� d'un nombre n�gatif est toujours positif.

En C ISO, il y a un overflow et c'est un UB. Dans un programme
conforme, l'oppos� d'un nombre n�gatif est toujours positif, et
le compilateur peut faire les optimisations correspondantes (ou
alors, avec gcc, il faut utiliser -fwrapv pour rendre ces UB
d�finis avec la s�mantique du compl�ment � 2, mais c'est une
extension).

Samuel Devulder

non lue,
31 oct. 2009, 19:14:2531/10/2009
à
Vincent Lefevre a �crit :

> Dans l'article <4aec7ca8$0$29451$426a...@news.free.fr>,
> Samuel Devulder <samuel-do...@geensys.com> �crit:
>
>> D'ailleurs la repr�sentation en compl�ment � 2 est assez dangereuse dans
>> le sens ou elle est "asym�trique". La valeur minimale est son propre
>> inverse (somm�e � elle m�me elle le r�sultat vaut z�ro), donc on ne peut
>> assumer que l'oppos� d'un nombre n�gatif est toujours positif.
>
> En C ISO, il y a un overflow et c'est un UB.

Et oui le fameux UB de la norme. Je l'aime d�cid�ment bien cet
argument... Si la norme le dit.. il n'y a rien d'autre � ajouter
finalement :) C'est beau les arguments d'autorit�s ya rien � discuter ;-)

> Dans un programme
> conforme, l'oppos� d'un nombre n�gatif est toujours positif, et

Le truc est qu'� en croire la norme, les programmes conformes ne sont
pas l�gions. J'ai lu que toutes les addition signed sont un risque
d'overflow et donc d'UB d'apr�s la norme. En revanche les overflow sur
unsigned ne font jammais d'UB et car ils "wrap" automatiquement. J'ai le
sentiment qu'on devrait le plus possible utiliser des unsigned au lieu
de int dans les progs pour ne pas risquer de soucis avec les UB de
l'arithm�tique sign�e.

En plus du fait de l'absence d'UB, il y a des chances que l'optimiseur
fasse un meilleur job. Exemple: en th�orie l'addition est associative
avec les unsigned, mais pas avec les signed car l'associativit� sur les
signed risque d'introduire des UB.

Y a t'il une raison de favoriser les signed au lieu des unsigned dans
les progs? Des raisons Historique? Pratiques? (on pr�f�re faire un
int i = ...;
while(--i>=0) {...}
plutot qu'un
unsigned i = ...;
while(i-->0) {...}
?)

sam.

candide

non lue,
31 oct. 2009, 19:44:1631/10/2009
à
Pierre Maurette a �crit :

> Vous m'�tonnez. CF plus haut. Rassurez-moi: vous �tes dans l'Education
> Nationale ?
>

Tiens, �a me fait penser � cette phrase de Cocteau qui dit grosso modo :

"Puisque ces �v�nements nous sont incompr�hensibles, feignons d'en �tre
les organisateurs".

J'ai bien l'impression que vous �tes ce qu'on appelle "un mauvais
perdant". Car en r�alit�, vous �tiez bien incapable de r�pondre � ma
question, vous ignoriez sans doute ce comportement du compilateur de MS,
vous vous �tes m�pris en confondant du bruit et un signal et vous
essayez de cacher ce bruit qui fait mal � vos oreilles en tentant de me
ridiculiser.


Reprenons mon code initial. Avec N=10000.

1�) Sous gcc, le temps d'un test "bruit�" est d'environ 1 s. Si on
d�truit le bruit (plus de pointeur de fonction, et m�me plus de
fonction, affichage r�duit au minimum et qu'il ne faut pas compl�tement
supprimer sous peine que le calcul ne soit pas effectu� � cause des
optimisations, suppression de la double boucle) :

#define TEST(f) {\
unsigned s = 0;\
int i;\
s = 0;\
\
for (i = 0; i < 100000000; i++)\
s += (unsigned)f(i);\
printf("%u\n",s);\
}


on obtient environ 0.2 s. Donc je n'appelle pas �a du bruit ("noy�es
dans le bruit" disiez-vous), c'est loin d'�tre n�gligeable. Il se trouve
par ailleurs en effet que si dans ma fonction du premier code on
retourne 0 au lieu de !(n%2) le temps est inchang�, je ne me l'explique
pas mais il n'emp�che qu'un calcul ou un autre utilise quand m�me 1/5
incompressible du temps du test.

2�) Mais il n'y avait pas d'interrogations concernant gcc. Le point
portait sur Visual. Les �carts de temps observ�s devaient au moins
soulever un doute (justifi�, comme la suite de la discussion l'a
montr�). Mais Monsieur Maurette pr�f�re se dire que ce n'est que du
bruit d'un programmeur du dimanche.

Je d�bruite le code initial en ceci :


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

#define f0(n) (!((n) & 0x1))
#define f1(n) (!((n) % 2))
#define f2(n) (!((n) % 2U))

#define f3(n) (42)
#define N 10000

#define TEST(f ) {\
clock_t now=clock();\
unsigned s = 0;\
int i,j;\


s = 0;\
\
for (i = 0; i < N; i++)\
for (j = 0; j < N; j++)\
s += (unsigned)f(i*j);\

printf("%u\n",s);\
printf("%.2f\n",(double) (clock() - now) / CLOCKS_PER_SEC);}

int main(void)
{
//TEST(f0)
//TEST(f1)
//TEST(f2)
//TEST(f1)

return 0;
}

*) Pour f0, le temps mis en moyenne selon est de 0.16s (au lieu de 1s)
donc effectivement il y avait beaucoup de bruit.
*) Par contre pour f1, le temps mis est en moyenne de 0.75s au lieu
1.42s pour le code initial donc, c'est loin loin d'�tre du bruit. M�me
si je supprime la double boucle par
for (i = 0; i < N*N; i++)\
s += (unsigned)f(i);\
j'obtiens en moyenne un temps presque �quivalent (0.65s).

Une fois de plus, vous n'avez pas su appr�cier le probl�me � sa juste
complexit� et vous pouvez m�me me remercier de vous avoir fait apprendre
quelque chose ;)


-ed-

non lue,
1 nov. 2009, 04:46:2401/11/2009
à
On 31 oct, 12:53, Éric Lévénez <use...@levenez.com> wrote:
> -ed- a écrit :

> >>         printf("estpair%d : %.2lf secondes\n\n",  j, duree/NB_TESTS);
>
> > N'existe pas. C'est
>
> >          printf("estpair%d : %.2f secondes\n\n",  j, duree/NB_TESTS);
>

> Non. "%lf" est tout à fait valide, même s'il est plus courant d'écrire "%f".

Oui, c'est correct en C99, mais pas en C90 (où c'est gentiment toléré
par la plupart des compilateurs).

-ed-

non lue,
1 nov. 2009, 04:56:1801/11/2009
à
On 31 oct, 17:58, Pierre Maurette <maurettepie...@wanadoo.fr> wrote:
> Ce que je veux dire, c'est qu'en C, les variables sont signées, et ça
> fout un grosse merde.

Les variables sont signée ou non. Question de définition.

Il est probable que sur la plupart des machines, le code de calcul
produit avec des variables signées soit plus complexe qu'avec des
variables non signées.

candide

non lue,
1 nov. 2009, 05:23:4201/11/2009
à
�ric L�v�nez a �crit :

> Non. "%lf" est tout � fait valide, m�me s'il est plus courant d'�crire
> "%f".
>


Ah oui, tu avais raison, la Norme dit :

7.19.6.1 The fprintf function

p7

l (ell) [...]or has no effect on a following a, A, e, E, f, F, g, or G
conversion specifier.

Par contre pour un long double c'est un L majuscule !

Marc Espie

non lue,
1 nov. 2009, 05:56:0501/11/2009
à
In article <4aec7ca8$0$29451$426a...@news.free.fr>,

Samuel Devulder <samuel-do...@geensys.com> wrote:
>Oui, tu veux dire qu'en ASM on doit savoir ce que l'on fait.
<sarcasme>Parce qu'en C, c'est pas la meme chose ? Je croyais que c'etait
reserve a Java, ce genre de souci...</sarcasme>

>En fait le soucis est que l'on ne pense pas naturellement en compl�ment � 2.
>Je suis persuad� que beaucoup, si
>ce n'est tous pensent intuitivement "positif" ou �ventuellement avec un
>bit de signe s�par� du reste comme dans les float IEEE (donc 2 valeurs
>de z�ro). Cela n'aide pas � �crire des expressions valides
>ind�pendamment du signe.

De toutes facons, le complement a 2 n'est pas garanti, ca n'est jamais
qu'une des representations possibles pour les entiers signes (je te l'accorde,
c'est la plus repandue aujourd'hui).

Si on se pose des questions de micro-optimisation, ca aide de connaitre
l'assembleur. Et le code genere. On pourra, comme le fait candide, regarder
aussi longtemps qu'on veut le code source, modifier les trucs pour essayer
d'obtenir des resultats... ca a a peu pres autant de chance d'aboutir que
l'alchimiste du moyen age essayant d'obtenir la transmutation de la matiere.

Surtout qu'en plus la tres sainte Norme ne dit rien sur les performances du
code, et que les compilo sont vraiment plus ou moins futes...

A cote de ca, meme si c'est pedagogiquement interessant, je me garde en
general de me plonger dans ce niveau de detail. Ca a une tendance naturelle
a obfusquer gravement le code, et a cacher de vraies grosses opportunites
d'optimisations qui elles, ne vont pas se compter en pouiemes de
micro-secondes.

Faire du code qui va vite, c'est un art. Eviter des micro-constructions qui
rament, c'est bien, mais c'est pas avec ca qu'on fait du code rapide, et
tu le sais aussi bien que moi...

Marc Espie

non lue,
1 nov. 2009, 06:03:1901/11/2009
à
In article <4aecc4e0$0$22236$426a...@news.free.fr>,

Samuel Devulder <samuel-do...@geensys.com> wrote:
>Le truc est qu'� en croire la norme, les programmes conformes ne sont
>pas l�gions. J'ai lu que toutes les addition signed sont un risque
>d'overflow et donc d'UB d'apr�s la norme. En revanche les overflow sur
>unsigned ne font jammais d'UB et car ils "wrap" automatiquement. J'ai le
>sentiment qu'on devrait le plus possible utiliser des unsigned au lieu
>de int dans les progs pour ne pas risquer de soucis avec les UB de
>l'arithm�tique sign�e.
>
>En plus du fait de l'absence d'UB, il y a des chances que l'optimiseur
>fasse un meilleur job. Exemple: en th�orie l'addition est associative
>avec les unsigned, mais pas avec les signed car l'associativit� sur les
>signed risque d'introduire des UB.
>
>Y a t'il une raison de favoriser les signed au lieu des unsigned dans
>les progs? Des raisons Historique? Pratiques? (on pr�f�re faire un
> int i = ...;
> while(--i>=0) {...}
>plutot qu'un
> unsigned i = ...;
> while(i-->0) {...}
>?)

Juste, la plupart des gens se gauffrent regulierement avec les comparaisons
en presence d'unsigned, ou utilisent des macros qui vont merder de facon
interessante. Typiquement, comment tu fais pour verifier que deux nombres
sont proches ? Avec des valeurs signees, tu sors abs de ton chapeau, et tu
ecris: if (abs(a-b) < 5)
En non-signe, il faut avoir la presence d'esprit de sortir un:
#define absdiff(a, b) ((a) < (b) ? (b) - (a) : (a) - (b))
if (absdiff(a, b) < 5)

sans compter que la quasi-totalite de la bibliotheque standard et des
bibliotheques que tu peux utiliser bossent avec des entiers signes...
donc ca va se bousculer au balcon cote verification des parametres.

Exception: size_t. C'est impressionnant les bugs lies a size_t. Ca ne fait
guere que quelques annees que les bibliotheques standard embarquent un
calloc() qui fonctionnent... Ben ouais, a la place d'un UB, on obtient
des debordements de capacite parfaitement documentes si on multiplie deux
valeurs trop grandes. C'est un schema d'attaque classique et parfaitement
connu (a l'origine d'un trou dans ssh, et d'un trou dans le flashplayer,
si ma memoire est bonne).

A l'arrivee, plein de gens preferent avoir parfois un UB plutot que des
bugs un peu abscons concernant leurs tests...

Vincent Lefevre

non lue,
1 nov. 2009, 07:14:3601/11/2009
à
Dans l'article <4aecc4e0$0$22236$426a...@news.free.fr>,
Samuel Devulder <samuel-do...@geensys.com> �crit:

> Vincent Lefevre a �crit :


> > Dans un programme conforme, l'oppos� d'un nombre n�gatif est
> > toujours positif, et

> Le truc est qu'� en croire la norme, les programmes conformes ne sont
> pas l�gions. J'ai lu que toutes les addition signed sont un risque
> d'overflow et donc d'UB d'apr�s la norme. En revanche les overflow sur
> unsigned ne font jammais d'UB et car ils "wrap" automatiquement. J'ai le
> sentiment qu'on devrait le plus possible utiliser des unsigned au lieu
> de int dans les progs pour ne pas risquer de soucis avec les UB de
> l'arithm�tique sign�e.

Le fait que �a wrappe n'est pas forc�ment le comportement voulu par
l'utilisateur. Dans ce cas, la solution n'est pas d'utiliser un type
non sign� (sauf si les quelques valeurs positives suppl�mentaires
suffisent), mais un type plus grand, et de valider son logiciel.
Sinon, �a fait comme Ariane 5.

D'autre part, on a parfois besoin de types sign�s pour repr�senter
des valeurs n�gatives, et mixer les types sign�s et les types non
sign�s est dangereux (surtout s'ils sont de tailles diff�rentes) �
cause des conversions implicites.

> En plus du fait de l'absence d'UB, il y a des chances que l'optimiseur
> fasse un meilleur job.

C'est plut�t l'inverse.

> Exemple: en th�orie l'addition est associative avec les unsigned,
> mais pas avec les signed car l'associativit� sur les signed risque
> d'introduire des UB.

Non, la notion d'UB existe dans le source C, mais comme en pratique,
le processeur calcule en compl�ment � 2, les optimisations sur les
nombres sign�s restent valides.

Éric Lévénez

non lue,
1 nov. 2009, 12:23:2901/11/2009
à
-ed- a �crit :
> On 31 oct, 12:53, �ric L�v�nez <use...@levenez.com> wrote:
>> -ed- a �crit :

>
>>>> printf("estpair%d : %.2lf secondes\n\n", j, duree/NB_TESTS);
>>> N'existe pas. C'est
>>> printf("estpair%d : %.2f secondes\n\n", j, duree/NB_TESTS);
>> Non. "%lf" est tout � fait valide, m�me s'il est plus courant d'�crire "%f".

>
> Oui, c'est correct en C99, mais pas en C90

C'est amusant (enfin pas vraiment), de toujours rappeler les vieilles
normes. Pourquoi donc ne pas rappeler � chaque fois la compatibilit� ou
non avec *toutes* les versions pr�c�dentes jusqu'au tout premier C de
1972, pourquoi te limites-tu au C90 ? C'est 19 ans ta limite ? En 2010
tu feras toujours la m�me chose ? :->

candide

non lue,
1 nov. 2009, 14:41:4501/11/2009
à
�ric L�v�nez a �crit :

> C'est amusant (enfin pas vraiment), de toujours rappeler les vieilles


> normes. Pourquoi donc ne pas rappeler � chaque fois la compatibilit� ou
> non avec *toutes* les versions pr�c�dentes jusqu'au tout premier C de
> 1972, pourquoi te limites-tu au C90 ? C'est 19 ans ta limite ? En 2010
> tu feras toujours la m�me chose ? :->
>

Quelqu'un a qualifi� -ed- d'int�griste tout � l'heure, j'avais envie
d'ajouter "integriste chapelle C90".

D�j� le probl�me avec la Norme C90 c'est qu'elle est introuvable, il me
semble qu'elle n'est m�me plus en vente � l'ISO. J'ai la version papier
�dit�e par H. Schildt mais elle a �t� mal �dit�e et une page sur
fprint() a �t� oubli�e, en plus il y a eu de substantielles modif en
1995 qui ne figurent pas dans le livre. Moi je trouve que pour la partie
commune entre les deux Normes, le texte de C99 est beaucoup plus pr�cis.

N�anmoins C90 reste quand m�me tr�s utilis�e (d�j� Visual C++). Et par
exemple CPython est totalement �crit en C ansi. Donc je comprends que
l'on reste attach� � C90.

Marc Espie

non lue,
1 nov. 2009, 15:14:4601/11/2009
à
In article <4aede479$0$30846$426a...@news.free.fr>,

candide <can...@free.invalid> wrote:
>�ric L�v�nez a �crit :
>
>> C'est amusant (enfin pas vraiment), de toujours rappeler les vieilles
>> normes. Pourquoi donc ne pas rappeler � chaque fois la compatibilit� ou
>> non avec *toutes* les versions pr�c�dentes jusqu'au tout premier C de
>> 1972, pourquoi te limites-tu au C90 ? C'est 19 ans ta limite ? En 2010
>> tu feras toujours la m�me chose ? :->
>>
>
>Quelqu'un a qualifi� -ed- d'int�griste tout � l'heure, j'avais envie
>d'ajouter "integriste chapelle C90".
>
>D�j� le probl�me avec la Norme C90 c'est qu'elle est introuvable, il me
>semble qu'elle n'est m�me plus en vente � l'ISO. J'ai la version papier
>�dit�e par H. Schildt mais elle a �t� mal �dit�e et une page sur
>fprint() a �t� oubli�e, en plus il y a eu de substantielles modif en
>1995 qui ne figurent pas dans le livre. Moi je trouve que pour la partie
>commune entre les deux Normes, le texte de C99 est beaucoup plus pr�cis.

Le seul interet de C90, c'est quand il y a des bouts de C99 qui ne sont
pas uniformement supportes. La difference etait tres importante il y a
5 ans, bien moins maintenant.

Le fait que le texte soit trouvable ou pas, c'est juste po juste pour les
chti djeunz comme toi. Les vieux cons dans mon genre, on a notre memoire
pour nous, et on sait sur quoi on s'est fait avoir, ou pas.

Ne pas oublier la marche inexorable du progres (et les conneries integristes
de la FSF, du cote "je ne separe pas ma front-end de ma back-end", qui font
que certains processeurs ne sont pas pleinement supportes par gcc 3.
ce qui fait par exemple que certaines constructions C99 (definitions de
variable n'importe ou dans le bloc) sont interdites dans OpenBSD... juste
parce qu'on supporte encore et toujours des archis qui n'ont pas pu passer
en gcc3...

... et donc que les distinctions C89/C99, au moins pour certaines, ont
encore leur importance pratique.

Pour un candide qui ne pratique le C que en tant qu'exercice theorique,
bien sur, ce genre de pinaillage ne presente aucun interet... ;-/

Vincent Lefevre

non lue,
1 nov. 2009, 21:09:5701/11/2009
à
Dans l'article <4aede479$0$30846$426a...@news.free.fr>,
candide <can...@free.invalid> �crit:

> N�anmoins C90 reste quand m�me tr�s utilis�e (d�j� Visual C++). Et par
> exemple CPython est totalement �crit en C ansi. Donc je comprends que
> l'on reste attach� � C90.

GCC se base aussi sur C90 par d�faut, si bien que si on ne passe pas
-std=c99 (ou gnu99), il y a des choses qui ne marchent pas.

-ed-

non lue,
2 nov. 2009, 06:01:2702/11/2009
à
On 1 nov, 18:23, Éric Lévénez <use...@levenez.com> wrote:
> > Oui, c'est correct en C99, mais pas en C90
>
> C'est amusant (enfin pas vraiment), de toujours rappeler les vieilles
> normes. Pourquoi donc ne pas rappeler à chaque fois la compatibilité ou

C99 n'est pas encore aussi déployée que C90.

- Inconnu chez Microsoft
- Incomplet chez gcc

C90 reste encore la norme de fait.

Rien à voir avec un quelconque intégrisme comme j'ai pu le lire plus
loin.

Le message a été supprimé

candide

non lue,
2 nov. 2009, 09:55:4102/11/2009
à
-ed- a �crit :
>
> http://delahaye.emmanuel.free.fr/c90/ansi_c99.pdf

ERREUR 404 - Document non trouv�

C'est bien ce que je dis, c'est introuvable ;)

candide

non lue,
2 nov. 2009, 15:04:2202/11/2009
à
Vincent Lefevre a �crit :

> GCC se base aussi sur C90 par d�faut, si bien que si on ne passe pas
> -std=c99 (ou gnu99), il y a des choses qui ne marchent pas.
>

Tiens, je viens de me rendre compte d'une diff�rence entre C90 et C99
plus ou moins en rapport avec le probl�me initial : en C90, lorsqu'un
des op�randes a ou b est n�gatif, le signe du reste a%b est d�fini par
l'impl�mentation. En C99 ce n'est plus le cas.

-ed-

non lue,
3 nov. 2009, 04:05:5403/11/2009
à
On 2 nov, 15:55, candide <cand...@free.invalid> wrote:
> -ed- a écrit :
>
>
>
> >http://delahaye.emmanuel.free.fr/c90/ansi_c99.pdf
>
> ERREUR 404 - Document non trouvé

>
> C'est bien ce que je dis, c'est introuvable ;)

Oui, je croyais l'avoir (en fait, c'est C99). Depuis, j'ai (tenté)
d'effacer mon message ... C'est pas facile sur Usenet...

Richard Delorme

non lue,
8 nov. 2009, 11:14:0208/11/2009
à
Le 02/11/2009 12:01, -ed- a �crit :

> On 1 nov, 18:23, �ric L�v�nez<use...@levenez.com> wrote:
>>> Oui, c'est correct en C99, mais pas en C90
>>
>> C'est amusant (enfin pas vraiment), de toujours rappeler les vieilles
>> normes. Pourquoi donc ne pas rappeler � chaque fois la compatibilit� ou
>
> C99 n'est pas encore aussi d�ploy�e que C90.
>
> - Inconnu chez Microsoft

Visual C++ 2010 (actuellement disponible en version b�ta) en supporte
des morceaux comme les macros variadiques, le type long long, les
commentaires � la C++. M�me si cela reste tr�s incomplet on ne peut pas
dire que le C99 soit inconnu de Microsoft. Il semble que la politique de
Microsoft soit d'ajouter des bouts de C99 en fonctions de la demande des
utilisateurs.� leurs utilisateurs de mieux r�clamer, donc.

> C90 reste encore la norme de fait.

On est quand m�me assez limit� par cette norme. Rien qu'une fonction
comme snprintf apporte une confort s�curitaire non n�gligeable par
rapport � sprintf.

> Rien � voir avec un quelconque int�grisme comme j'ai pu le lire plus
> loin.

Mmmmmm....

--
Richard

Antoine Leca

non lue,
16 nov. 2009, 06:42:4516/11/2009
à
candide a �crit :

> -ed- a �crit :
>> On 29 oct, 23:14, candide <cand...@free.invalid> wrote:
>>
>>> #define N (unsigned int)10000
>> Une fa�on compliqu� et erron�e
>
> Pourquoi erron�e ?

Un exemple outr� mais simple � comprendre :

float x, *p;
/* ... */
x = N[p];

Et hop! tu r�cup�res un arrondi par d�faut que normalement tu n'esp�res
pas (et si c'est fait expr�s, c'est OK pour l'IOCCC).

Antoine

0 nouveau message