Précédent   Forum du club des développeurs et IT Pro > C et C++ > C
C Forum d'entraide technique sur le langage C. Avant de poster -> F.A.Q. C, Avant de poster.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Actualité déjà publiée
 
Outils de la discussion
Publicité
'
Vieux 09/01/2012, 18h52   #21
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 589
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 589
Points : 11 921
Points : 11 921
Citation:
Envoyé par Bousk Voir le message
http://en.wikipedia.org/wiki/Restrict
je connaissais pas ce mot-clé
c'est finalement pas stupide du tout, un tel exemple ne me serait certainement jamais apparu

l'exmple donné est stupide et disparaîr dès que l'on se penche sur l'optimisation d'un code : n'importe qui qui voit une valeur à calculer apparaître 2 fois la factorise..

Et cela aurrait dû être fait par le compilateur, automatiquement dans les options O1 , O2, ou O3

Je ne vois pas ce que ajouter un élément d'optimisation à la norme d'un langage ajooute, à part le fait de le rendre moins général... et compliquer la vie de ceux qui l'apprennent..

Et si un pomgrammeur était assez stupide pour faire pointer par B ou A le même buffer que val (dans le bon ordre), alors il n'a rien à faire à programmer des choses complexes...

C'estcomme pour la rotation d'un point x,y.. Si le programmeur est assez stupide pour ne pas se servir des coordonnées AVANT les opérations, ben..il n'y a plus rien à faire pour lui..

Je troue cela aberrant : alors ça marche pour un truc,mais pas si on complexifie la tâche (comme l'exemple de la rotation)..

Et , par rapport au Fortran, la chose ne corrige rien : si on fait la même chose en Fortran, on obtiendra la même incertitude...
__________________
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java

Je ne réponds pas aux MP techniques
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/01/2012, 17h31   #22
rt15
Membre éprouvé
 
Avatar de rt15
 
Homme
Développeur informatique
Inscription : octobre 2005
Messages : 203
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2005
Messages : 203
Points : 435
Points : 435
Citation:
Envoyé par souviron34 Voir le message
l'exmple donné est stupide et disparaîr dès que l'on se penche sur l'optimisation d'un code : n'importe qui qui voit une valeur à calculer apparaître 2 fois la factorise..
Si on est soucieux des perfs, il me semble que l'on ne peut pas trouver ça stupide.
Et le compilo n'y peut rien. Si on ne lui dit pas que ça n'overlap pas, il ne peut pas deviner. Il est obligé de prendre en compte le cas de l'overlap...

On peut faire le parallèle avec memcpy/memmove.
D'un côté, memcpy est souvent plus rapide car il n'y a pas d'overlap (C'est du moins ce qu'est censé garantir le programmeur, comme pour restrict). De l'autre memmove gère l'overlap et est souvent plus lent.

De ce fait, memcpy est en quelque sorte l'implémentation de memmove avec des arguments restrict.

Bref, ajouter restrict permet littéralement de modifier le comportement d'une fonction et donc les optimisation possibles pour le compilo.
rt15 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/01/2012, 18h02   #23
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 589
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 589
Points : 11 921
Points : 11 921
Citation:
Envoyé par rt15 Voir le message
Si on est soucieux des perfs, il me semble que l'on ne peut pas trouver ça stupide.
Et le compilo n'y peut rien. Si on ne lui dit pas que ça n'overlap pas, il ne peut pas deviner. Il est obligé de prendre en compte le cas de l'overlap...

On peut faire le parallèle avec memcpy/memmove.
D'un côté, memcpy est souvent plus rapide car il n'y a pas d'overlap (C'est du moins ce qu'est censé garantir le programmeur, comme pour restrict). De l'autre memmove gère l'overlap et est souvent plus lent.

De ce fait, memcpy est en quelque sorte l'implémentation de memmove avec des arguments restrict.

Bref, ajouter restrict permet littéralement de modifier le comportement d'une fonction et donc les optimisation possibles pour le compilo.
Je répète :
  • ajouter restrict vient du programmeur
  • utiliser correctement memcpy ou memmove vient du programmeur
  • Faire une idiotie vient du programmeur..

Faire

Code :
memmove ( &(tab[2]), &(tab1), (n-2)*sizeof(...));
est tout à fait légal, de même que faire

Code :
memmove ( &(tab[1]), &(tab2), (n-2)*sizeof(...));
Sauf qu'il faut avoir lu la doc et savoir ce qu'on fait..

Pourquoi faudrait-il avoir un paramètre à un compilo pour empêcher de faire ça ??

Et si la fonction est f(a,b,c), et que a, b, et c sont des tableaux, ou alors on les programmeurs sont des c.ns de pas avoir lu la doc ou alors c'est qu'on n'a pas fourni la bonne doc...


Je trouve que c'est vraiment inutile (surtout dans une norme de langage), et que cela va à l'encontre et de la souplesse / rigueur qu'implique le C et de la symbolique des options de compil -O1, -O2, ou -O3, qui "optimisent" de la meilleure manière, sans que le programmeur ait à savoir quoi : on peut même s'apercvoir que, dans d'assez nombreux cas justement -O3 optimise trop, avec le genre de mécanisme décrit dans le lien..

Sauf que justement c'est une option de compil...


Et comme je disais, cela ne rapproche en rien du Fortran..

Si une routine Fortran est f(a,b,c), et que la doc dit que A, B, et C dovent être différents, ce n'est pas Fortran qui va râler en tant que tel si le programmeur utilise le même tableau..

Ce genre de manip est aux risques et périls de l'utilisateur, il faut savoir ce qu'on fait..

Il y a plein d'exemples en C : les fonctions de tris de qsort, les sockets, les unions, les doubles pointeurs, les void*, etc etc..
__________________
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java

Je ne réponds pas aux MP techniques
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 11h57   #24
rt15
Membre éprouvé
 
Avatar de rt15
 
Homme
Développeur informatique
Inscription : octobre 2005
Messages : 203
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2005
Messages : 203
Points : 435
Points : 435
Le but de restrict n'est pas du tout d'empêcher le développeur ou le compilateur de faire des bêtises.
Le but est de préciser au compilo qu'il n'y a pas d'overlap.
Cette information permet au compilo de générer un code plus rapide dans certains cas.
Et le compilo ne peut généralement pas deviner cette information que l'on utilise -O3 ou pas. Pour le déterminer, il faut qu'il vérifie dans le source que lors des appels (Ou de l'appel, si la fonction est inliné) qu'il ne peut pas y avoir d'overlap car les paramètres sont "différents". Jolie casse tête. Et dans certains cas, c'est même tout à fait impossible car il ne peut pas connaître tous les appels d'avance (Cas d'une fonction exportée par une librairie).

Considérons une fonction plus proche de ce qui peut exister, c'est à dire une fonction updatePoints qui prend en paramètre :
1/ Un tableau de points(Coordonnées x et y).
2/ Le nombre d'élément du tableau.
3/ Un pointeur vers un point delta.

Le but de la fonction est d'ajouter à tous les points du tableau le delta contenu dans le paramètre trois.
Code :
1
2
3
4
pour i de 0 à n - 1
  points[i].x += delta.x;
  points[i].y += delta.y;
fait;
Ca revient à peu près à une bête translation d'un nuage de points dans un espace 2D. D'un point de vue fonctionnel, il n'y aura a jamais d'overlap entre "points" et "delta". Le programmeur le sait. Le compilo ne le sait pas forcément si le programmeur ne lui indique pas.

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
 
#define POINT_COUNT 4
 
typedef struct
{
  int x;
  int y;
}
MY_POINT;
 
void updatePoints1(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  int i;
 
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints[i].x += lpDelta->x;
    lpPoints[i].y += lpDelta->y;
  }
}
 
void updatePoints2(MY_POINT *restrict lpPoints, int nPointCount, MY_POINT *restrict lpDelta)
{
  int i;
 
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints[i].x += lpDelta->x;
    lpPoints[i].y += lpDelta->y;
  }
}
 
int main()
{
  int i;
  MY_POINT lpPoints[4];
  MY_POINT delta;
 
  for (i = 0; i < POINT_COUNT; i++)
  {
    lpPoints[i].x = i;
    lpPoints[i].y = 100 + i;
  }
  delta.x = 1;
  delta.y = 1;
  updatePoints1(lpPoints, POINT_COUNT, &delta);
  updatePoints2(lpPoints, POINT_COUNT, &delta);
 
  for (i = 0; i < POINT_COUNT; i++)
  {
    printf("%d %d\n", lpPoints[i].x, lpPoints[i].y);
  }
 
  return 0;
}

La différence entre updatePoints1 et updatePoints2 est simplement l'ajout du mot clé restrict. La différence se fait dans le code généré. En effet, comme restrict indique que delta n'est pas modifié quand lpPoints est modifié, la valeur de delta n'a pas à être lue à chaque tour de boucle.

Code sans restrict :
Code :
1
2
3
4
5
6
7
8
loop:
mov     ecx,[esi]               # ecx = delta.x
mov     eax,[esi+0x4]           # eax = delta.y
add     [ebx+edx*8],ecx         # points[i].x += ecx
add     [ebx+edx*8+0x4],eax     # points[i].y += eax
inc     edx                     # i++
cmp     edx,0x4                 # si i < 4 alors ...
jl      loop                    # ... saute à loop
Code avec restrict :
Code :
1
2
3
4
5
6
7
8
mov     ecx,[esi]
mov     eax,[esi+0x4]
loop:
add     [ebx+edx*8],ecx
add     [ebx+edx*8+0x4],eax
inc     edx
cmp     edx,0x4
jl      loop
Le corps de la boucle (Ce qui est exécuté 1000 fois s'il y a 1000 éléments) a 2 instructions de moins. D'autre part, toujours dans le cas de restrict, on peut inverser la boucle et ainsi remplacer inc/cmp/jl par dec/jnz et gagner une autre instruction. On ne peut pas faire cette inversion sans restrict car si delta peut être un élément de points, le résultat peut dépendre du sens de parcourt.

Bref, restrict, c'est une information qui en théorie peut bien aider le compilo à générer du code plus rapide. Il semble donc intéressant de l'avoir dans la norme.

[ ************** edit ************** ]
A noter que dans les faits, avec les flags de compilation :
gcc -O3 test.c -o test.exe -std=c99 -fstrict-aliasing
gcc 3.4.5 (Version ancienne... Il semble qu'il y ait eu des amélioration de restrict en 4.5) ne réalise pas l'optimisation permise par restrict ci-dessus.

Par contre, on peut forcer gcc 3.4.5 à réaliser l'optimisation en faisant une copie du contenu de lpDelta dans une variable locale. Le code C paraît alors moins optimisé, mais le code machine généré est comme celui ci-dessus "avec restrict".

Code c :
1
2
3
4
5
6
7
8
9
10
11
12
13
void updatePoints1(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  int i;
  MY_POINT delta;
 
  delta = *lpDelta;
 
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints[i].x += delta.x;
    lpPoints[i].y += delta.y;
  }
}

[ ************** edit 2 ************** ]
gcc 4.6.1 réalise correctement l'optimisation avec le mot clé restrict.
(Et il fait aussi l'optimisation en cas de copie locale de delta comme ci-dessus)
rt15 est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 17/01/2012, 13h15   #25
gangsoleil
Modérateur
 
Avatar de gangsoleil
 
R&D en systemes informatiques bas niveau Unix/Linux
Inscription : mai 2004
Messages : 7 191
Détails du profil
Informations personnelles :
Âge : 32
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : R&D en systemes informatiques bas niveau Unix/Linux

Informations forums :
Inscription : mai 2004
Messages : 7 191
Points : 18 081
Points : 18 081
Citation:
Envoyé par rt15 Voir le message
Bref, restrict, c'est une information qui en théorie peut bien aider le compilo à générer du code plus rapide. Il semble donc intéressant de l'avoir dans la norme.
Je suis d'accord avec tes arguments sur l'utilite d'un tel outil pour un compilateur, mais pas dans un langage. Les directives de compilation, ca existe deja, mais je ne vois pas en quoi il est interessant d'ajouter au langage un mot-clef reserve aux optimisations du compilateur.

Un autre exemple serait, par exemple, le fait de preciser si un test de boucle est probablement pris ou non (si mes souvenirs sont bons : pnt pour ceux qui ont fait de l'assembleur Sparc).
Par exemple, dans le cas du test du retour d'un appel a malloc/calloc, il est peu probable que le code de traitement de l'erreur soit appele (ou dans ce cas, il est probable que l'on quitte le programme), et donc le fait que le code "probablement execute" soit proche et le code "probablement pas execute" soit loin est une information interessante, et les gains ne sont pas negligeables (non, je n'ai plus les informations).
Mais est-ce que, pour autant, cette option de compilation doit etre introduite dans le langage sous forme de l'ajout d'un mot-clef ?
__________________
Modérateur "C", "Informatique Générale & Hardware" et "Unix"
Les règles du forum
gangsoleil est déconnecté   Envoyer un message privé Réponse avec citation 01
Vieux 17/01/2012, 14h17   #26
Bousk
Modérateur
 
Homme Cyrille
Network programmer
Inscription : juin 2010
Messages : 1 551
Détails du profil
Informations personnelles :
Nom : Homme Cyrille
Âge : 25
Localisation : France

Informations professionnelles :
Activité : Network programmer

Informations forums :
Inscription : juin 2010
Messages : 1 551
Points : 4 098
Points : 4 098
Citation:
Envoyé par gangsoleil Voir le message
Mais est-ce que, pour autant, cette option de compilation doit etre introduite dans le langage sous forme de l'ajout d'un mot-clef ?
Je me pose la question inverse : est-ce que ça pourrait être introduit avec seulement une option de compilation ?
Ca semble bien être une option du langage sur les paramètres des fonctions de notre choix, pour indiquer au compilo l'optimisation à réaliser. Je vois pas comment le compilo pourrait en être conscient avec une simple option de compilation, tout en gardant le fonctionnement possible sans le restrict de temps en temps (ou inversement).

edit : jean-marc ci-dessous a parfaitement réécrit ma pensée.
Bousk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 14h26   #27
Jean-Marc.Bourguet
Expert Confirmé Sénior

 
Inscription : novembre 2005
Messages : 4 970
Détails du profil
Informations forums :
Inscription : novembre 2005
Messages : 4 970
Points : 5 607
Points : 5 607
Citation:
Envoyé par gangsoleil Voir le message
Mais est-ce que, pour autant, cette option de compilation doit etre introduite dans le langage sous forme de l'ajout d'un mot-clef ?
Ajouter restrict peut changer un programme valide en un programme non conforme (supprimer un restrict ne devrait pas le faire), ça peut donc sembler du ressort du langage plus que des annotations.
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Jean-Marc.Bourguet est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/01/2012, 16h53   #28
gangsoleil
Modérateur
 
Avatar de gangsoleil
 
R&D en systemes informatiques bas niveau Unix/Linux
Inscription : mai 2004
Messages : 7 191
Détails du profil
Informations personnelles :
Âge : 32
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : R&D en systemes informatiques bas niveau Unix/Linux

Informations forums :
Inscription : mai 2004
Messages : 7 191
Points : 18 081
Points : 18 081
Citation:
Envoyé par Jean-Marc.Bourguet Voir le message
Ajouter restrict peut changer un programme valide en un programme non conforme
Je comprends bien cet argument, et suis relativement d'accord avec. Mais le C est, a la base, un langage permettant de faire tout ce que l'on veut (y compris le pire), sans verification.
On peut citer par exemple realloc, souvent mal utilise au point que si l'allocation echoue, il y a une fuite memoire, ou bien encore le fait que les commandes memcpy et memmov existent en parallele.

Oui, il est tout a fait possible de modifier le C pour que realloc se comporte a ne pas modifier le pointeur si l'allocation echoue, ou bien encore de supprimer memcpy pour ne garder que memmov qui fonctionne dans tous les cas, ou bien d'introduire de nouveaux mots-clef pour que le developpeur puisse ajouter une restriction ici ou la.
Dans certains cas, comme avec restrict, ce gain sera visible dans l'executable, ce qui peut sembler une bonne chose. Dans d'autres cas, ce gain serait visible en refusant par exemple de compiler certaines erreurs classiques, ce qui eviterait de voir ici des posts du genre "mon programme segfault alors qu'il est correct".
Mais est-ce que le gain est reel ?
__________________
Modérateur "C", "Informatique Générale & Hardware" et "Unix"
Les règles du forum
gangsoleil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/01/2012, 18h55   #29
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 589
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 589
Points : 11 921
Points : 11 921
Citation:
Envoyé par gangsoleil Voir le message
Mais est-ce que le gain est reel ?
That is the question...

Et c'est bien ça qui m'embête : à ajouter inline, restrict, etc etc, on finit par transformer un langage de programmation en un langage où il y a mélange entre programmation et instructions d'optimisation de compilateur..

Ce qui, de mon point de vue, est une extrême mauvaise chose, ne povant qu'entraîner non seulement un usage abusif, non compatible, additionné d'un mélange des concepts, et surtout une fainéantise intellectuelle qui va à l'encotre de la philosophie du C..

Je ré-itère que c'est bien pour discuter des options d'optimisation qu'il y a des flags O2 ou O3..

Si je parlais en "OO", je dirais que la classe "programme" n'a pas à se soucier de la classe "exécutable" ni de sa méthode assoiciée "build"...
__________________
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java

Je ne réponds pas aux MP techniques
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2012, 17h54   #30
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 709
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Ingénieur systèmes embarqués
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 709
Points : 4 192
Points : 4 192
J'ai du mal à comprendre pourquoi certains ne "veulent" pas que ça soit un mot-clé du langage, car je ne vois pas comment le compilateur pourrait deviner le non chevauchement des entités... Si on souhaite avoir un tel mécanisme, il doit obligatoirement passer par un mot clé du langage, non ?

Après, j'entends parfaitement les arguments disant que ce n'est pas le rôle du langage de faire des optimisations mais au compilateur de se débrouiller. En même, il existe bien des directives #pragma pour influencer le compilateur (je ne m'en suis jamais servi perso ). On a aussi la possibilité de mettre un mot clé const à l'un des paramètres d'une fonction pour bloquer à la compilation quelque chose comme :

Code :
1
2
3
4
void maFonction(int const *a)
{
	(*a)++;
}
Ce genre de petits bonus dans le code me fait penser aux hints qu'on peut mettre dans le code SQL. Normalement, c'est le SGBD qui décide des plans d'exécutions mais il est parfois très utile de forcer un comportement quand on sait qu'il sera bénéfique.

Je trouve dommage de se priver d'"outils" pour faciliter la programmation ou améliorer la performance sous couvert d'une envie d'excellence, voire d'élitisme :
Citation:
Envoyé par souviron34
Ce qui, de mon point de vue, est une extrême mauvaise chose, ne povant qu'entraîner non seulement un usage abusif, non compatible, additionné d'un mélange des concepts, et surtout une fainéantise intellectuelle qui va à l'encotre de la philosophie du C..
Je suis d'accord qu'il faut savoir ce qu'on fait et être exigeant. Je ne suis pas sûr qu'ajouter un mot-clé comme restrict (et au contraire de const ?) amène à la fainéantise, bien au contraire : tu ne peux pas le mettre au hasard et te disant "au pire ça fera rien" (comme le disait TJean-Marc.Bourguet).
__________________
Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

Pour vos problèmes d'embarqué, utilisez le forum dédié !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 18/01/2012, 18h29   #31
gangsoleil
Modérateur
 
Avatar de gangsoleil
 
R&D en systemes informatiques bas niveau Unix/Linux
Inscription : mai 2004
Messages : 7 191
Détails du profil
Informations personnelles :
Âge : 32
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : R&D en systemes informatiques bas niveau Unix/Linux

Informations forums :
Inscription : mai 2004
Messages : 7 191
Points : 18 081
Points : 18 081
Citation:
Envoyé par Bktero Voir le message
J'ai du mal à comprendre pourquoi certains ne "veulent" pas que ça soit un mot-clé du langage [...]
A mon sens, la question n'est pas de savoir si cela doit etre ou non un mot-clef du langage, mais si cela fait sens d'ajouter des mots-clefs pour surcharger le C.

Si on veut lister tous les concepts que l'on pourrait ajouter au C, on peut discuter longtemps : pourquoi ne pas ajouter un systeme de gestion des listes chainees, c'est quand meme vachement pratique. On pourrait aussi, pourquoi pas, ajouter la surcharge des operateurs, il y a des gens qui ont l'air de trouver ca vraiment genial. ...

Oui, une norme peut evoluer, ce n'est pas ce que je critique. Ce que je critique, ce sont les evolutions proposees dans cette nouvelle version, car je trouve que la plupart n'ont pas de raisons d'etre, et que d'autres manquent. Par exemple, pour la gestion des threads, que va-t-il se passer avec la gestion des signaux, sachant que threads et signaux ne font pas du tout bon menage ? C'est au compilateur de s'en debrouiller, ou bien au developpeur, ou bien au systeme ?

[troll]
Et puis lorsqu'on voit comment a ete implementee C99, et que l'on se dit que C11 est dans la droite ligne de son predecesseur, on se dit que de toute maniere, C11 sera aussi inimplementee que C99, et que donc ce n'etait meme pas la peine de la sortir
[/troll]
__________________
Modérateur "C", "Informatique Générale & Hardware" et "Unix"
Les règles du forum
gangsoleil est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2012, 20h16   #32
Jean-Marc.Bourguet
Expert Confirmé Sénior

 
Inscription : novembre 2005
Messages : 4 970
Détails du profil
Informations forums :
Inscription : novembre 2005
Messages : 4 970
Points : 5 607
Points : 5 607
Citation:
Envoyé par Bktero Voir le message
J'ai du mal à comprendre pourquoi certains ne "veulent" pas que ça soit un mot-clé du langage,
Moi ce que j'ai parfois du mal à comprendre, c'est l'objet des interventions. On peut, sur restrict par exemple,
- ne pas comprendre à quoi ça sert,
- comprendre à quoi ça sert et préférer que l'objectif soit atteint d'une autre manière
- comprendre à quoi ça sert et trouver que ce n'est pas assez important pour être normalisé.
et certains s'expriment -- pour donner force à leur propos ? -- de manière ambigue ("je ne comprends pas pourquoi on a ajouté restrict" est quelque chose qui peut être écrit pour signifier les trois positions).

Ma position est la troisième (C99 a eu un très important accent numérique -- restrict, complex, des fonctions mathématiques -- qui a un intérêt relativement faible dans son domaine historique par rapport à la complexité que ça ajoute). Mais à partir du moment où c'est normalisé, le mot clé me semble la bonne méthode.
__________________
Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.
Jean-Marc.Bourguet est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/01/2012, 20h41   #33
rt15
Membre éprouvé
 
Avatar de rt15
 
Homme
Développeur informatique
Inscription : octobre 2005
Messages : 203
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2005
Messages : 203
Points : 435
Points : 435
Les développeurs C++ bavaient devant C++11. Ils trépignent en attendant que les compilos se mettent à jour.

Les développeurs C en sont encore à critiquer C99. Certains se demandent même si une quelconque évolution est nécessaire voire bénéfique.


Perso, je ne sais pas ce que j'aurai aimé voire dans C11.
rt15 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 19/01/2012, 01h05   #34
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 589
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 589
Points : 11 921
Points : 11 921
Citation:
Envoyé par rt15 Voir le message
Considérons une fonction plus proche de ce qui peut exister, c'est à dire une fonction updatePoints qui prend en paramètre :
1/ Un tableau de points(Coordonnées x et y).
2/ Le nombre d'élément du tableau.
3/ Un pointeur vers un point delta.
Et dis-moi ce que ton compilo te donnes en assembleur pour


Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void updatePoints1(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  int i, j, k;
 
   j = lpDelta->x ;
   k = lpdelta->y ;
 
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints->x += j;
    lpPoints->y += k;
    lpPoints++ ;
  }
}

ou bien

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void updatePoints1(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  register int i, j, k;
  register MY_POINT *ptr = lpPoints ;
 
   j = lpDelta->x ;
   k = lpdelta->y ;
 
  for (i = 0; i < nPointCount; i++)
  {
    ptr->x += j;
    ptr->y += k;
    ptr++ ;
  }
}



PS : ton "optimisation" montrée avec restrict est détruite par l'usage des indices dans le tableau : à chaque point tu fais deux multiplications et une addition pour calculer l'adresse, ce qui est nettement plus lent que l'optimisation montrée par l'usage de restrict...

Donc, c'est comme vouloir otimiser des if ou des switch.. .

L'optimisation est principalement dans l'algo et la réflexion (comme pour le calcul d'adresse ci-dessus : tu dois le faire 5 milliards de fois, ça coûte 10 milliards de multiplications de plus qu'incrémenter un pointeur...)



Citation:
Envoyé par Bktero Voir le message
Je trouve dommage de se priver d'"outils" pour faciliter la programmation ou améliorer la performance sous couvert d'une envie d'excellence, voire d'élitisme :
Je trouve simplement dommage, comme le disait gangsoleil, de mofieir une norme afin d'ajouter des choses qui d'une part n'ont rien à faire dans un langage de programmation et qui d'autre part peuvent être faites autrement ou ailleurs, là où c'est leur place normale....

Maintenant, je vais pas me batre dessus, mais je trouve simplement qu'on dérive vers une fois de plus (ce que ça n'était pas) un truc de geeks..c'est dans l'air du temps, ça ne m'empêche pas de ne pas être d'accord..


Citation:
Envoyé par rt15 Voir le message
Les développeurs C++ bavaient devant C++11. Ils trépignent en attendant que les compilos se mettent à jour.
Ben c'est peut-être ça le problème : des gens habtiués au C++ qui veulent changer C pour se sentir à l'aise
__________________
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java

Je ne réponds pas aux MP techniques
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/01/2012, 10h10   #35
rt15
Membre éprouvé
 
Avatar de rt15
 
Homme
Développeur informatique
Inscription : octobre 2005
Messages : 203
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2005
Messages : 203
Points : 435
Points : 435
Citation:
Envoyé par souviron34 Voir le message
Et dis-moi ce que ton compilo te donnes en assembleur pour
Bin... Avec gcc 4.6.1, il me génère exactement la même chose qu'avec restrict. Il n'inclus bien sûr pas la lecture de lpDelta à chaque tour de boucle du fait de la copie. Et il génère les mêmes adds (Alors qu'on pourrait s'attendre à ce qu'il incrémente les "pointeurs") :
Code :
1
2
add     [ebx+eax*8],edx
add     [ebx+eax*8+0x4],ecx
Je verrais plus tard si déplacer les pointeurs comme tu le fais dans ton C est plus rapide une fois retranscrite tel quel assembleur. Mais ce n'est pas dit... En effet, le eax * 8 a un cout probablement très faible. "8" est le scale qui ne peut valoir que 1, 2, 4 ou 8. Cette "multiplication" ne coûte peut être strictement rien...
rt15 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/01/2012, 11h21   #36
souviron34
Expert Confirmé Sénior
 
Inscription : janvier 2007
Messages : 9 589
Détails du profil
Informations personnelles :
Âge : 55

Informations forums :
Inscription : janvier 2007
Messages : 9 589
Points : 11 921
Points : 11 921
Citation:
Envoyé par rt15 Voir le message
Bin... Avec gcc 4.6.1, il me génère exactement la même chose qu'avec restrict....


Exactement ce que je disais..

Donc il n'y avait pas besoin de ce mot, pusiue avec ce qui existait on peut le faire
__________________
"Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

Consultant indépendant.
Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
C, Fortran, XWindow/Motif, Java

Je ne réponds pas aux MP techniques
souviron34 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/01/2012, 18h14   #37
rt15
Membre éprouvé
 
Avatar de rt15
 
Homme
Développeur informatique
Inscription : octobre 2005
Messages : 203
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 28
Localisation : France, Savoie (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique

Informations forums :
Inscription : octobre 2005
Messages : 203
Points : 435
Points : 435
Bench. Six écritures différentes de la fonction.
1/ C, implémentation innocente.
2/ C, copie de lpDelta (Ce qui revient à utiliser restrict).
3/ C, déplacement du pointeur de souviron34.
4/ ASM, stupide, relecture de lpDelta à chaque tour de boucle.
5/ ASM, en utilisant le scale.
6/ ASM, en déplaçant le pointeur.

Eh bin sous VC6, paramètre par défaut de compilation en release (/O2 apparemment), processeur intel core 2 cadencé à 2.33Ghz, ça donne égalité "parfaite". Le compilo a l'air pas mauvais et le processeur semble effacer les petites différences. Pour espérer gratter, faudrait regarder du côté des threads ou des d'instructions SIMD (Les gains ou pertes dépendrait beaucoup du nombre de points).

C'est vrai que vu sous cet angle, restrict, c'est pas franchement indispensable...

Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <stdio.h>
#include <windows.h>
 
#define POINT_COUNT 40000000
#define FUNCTION_TO_TEST_COUNT 6
#define TEST_COUNT 20
 
typedef struct
{
  int x;
  int y;
}
MY_POINT;
 
/* Proto des fonctions à tester */
typedef void (__stdcall* FUNCTION_TO_TEST) (MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta);
 
/* Contient le nom d'une fonction à tester et un pointeur sur celle-ci */
typedef struct _FUNCTION_TO_TEST_INFO
{
  char name[64];
  FUNCTION_TO_TEST function;
  int duration;
}
FUNCTION_TO_TEST_INFO;
 
/* Implémentation candide */
void __stdcall UpdatePointsSimple(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  int i;
 
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints[i].x += lpDelta->x;
    lpPoints[i].y += lpDelta->y;
  }
}
 
/* Implémentation avec copie de lpDelta (Revient à utiliser restrict) */
void __stdcall UpdatePointsCopyDelta(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  MY_POINT delta;
  int i;
 
  delta = *lpDelta;
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints[i].x += delta.x;
    lpPoints[i].y += delta.y;
  }
}
 
/* Plutôt que d'accèder par indice à lpPoints, on fait progresser un pointeur */
void __stdcall UpdatePointsMovePointer(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  register int i, j, k;
  register MY_POINT *ptr = lpPoints ;
 
   j = lpDelta->x ;
   k = lpDelta->y ;
 
  for (i = 0; i < nPointCount; i++)
  {
    ptr->x += j;
    ptr->y += k;
    ptr++ ;
  }
}
 
/* Code assembleur rechargeant depuis lpDelta */
__declspec(naked) void __stdcall UpdatePointsAsmReloadDelta(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  __asm
  {
    push edi
    push esi
    mov ecx, [esp + 16]            /* ecx = nPointCount    */
    mov esi, [esp + 20]            /* esi = lpDelta        */
    mov edi, [esp + 12]            /* edi = lpPoints       */
next:
    jecxz the_end                  /* Fin de loop si i = 0 */
    dec ecx                        /* i--                  */
    mov eax, [esi]                 /* eax = lpDelta.x      */
    mov edx, [esi + 4]             /* edx = lpDelta.y      */
    add [edi + ecx * 8], eax       /* lpPoints[i].x = eax  */
    add [edi + ecx * 8 + 4], edx   /* lpPoints[i].y = edx  */
    jmp next
the_end:
    pop esi
    pop edi
    ret 12
  }
}
 
/* Code assembleur utilisant le scale */
__declspec(naked) void __stdcall UpdatePointsAsmWithScale(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  __asm
  {
    push edi
    mov ecx, [esp + 12]            /* ecx = nPointCount    */
    mov edi, [esp + 16]            /* edi = lpDelta        */
    mov eax, [edi]                 /* eax = lpDelta.x      */
    mov edx, [edi + 4]             /* edx = lpDelta.y      */
    mov edi, [esp + 8]             /* edi = lpPoints       */
next:
    jecxz the_end                  /* Fin de loop si i = 0 */
    dec ecx                        /* i--                  */
    add [edi + ecx * 8], eax       /* lpPoints[i].x = eax  */
    add [edi + ecx * 8 + 4], edx   /* lpPoints[i].y = edx  */
    jmp next
the_end:
    pop edi
    ret 12
  }
}
 
/* Code assembleur faisant progresser le pointeur */
__declspec(naked) void __stdcall UpdatePointsAsmMovePointer(MY_POINT *lpPoints, int nPointCount, MY_POINT *lpDelta)
{
  __asm
  {
    mov ecx, [esp + 8]             /* ecx = nPointCount        */
    test ecx, ecx                  /* Vérification nPointCount */
    jz the_end
 
    push edi
 
    mov edi, [esp + 16]            /* edi = lpDelta            */
    mov eax, [edi]                 /* eax = lpDelta.x          */
    mov edx, [edi + 4]             /* edx = lpDelta.y          */
    mov edi, [esp + 8]             /* edi = lpPoints           */
next:
    add [edi], eax                 /* lpPoints->x = eax        */
    add [edi + 4], edx             /* lpPoints->y = edx        */
    add edi, 8                     /* lpPoints++               */
    dec ecx                        /* i--                      */
    jnz next                       /* loop si i > 0            */
 
    pop edi
the_end:
    ret 12
  }
}
 
/* Liste des fonctions à tester */
FUNCTION_TO_TEST_INFO updatePoints[FUNCTION_TO_TEST_COUNT] =
{
  {"UpdatePointsSimple",         UpdatePointsSimple, 0},
  {"UpdatePointsCopyDelta",      UpdatePointsCopyDelta, 0},
  {"UpdatePointsMovePointer",    UpdatePointsMovePointer, 0},
  {"UpdatePointsAsmReloadDelta", UpdatePointsAsmReloadDelta, 0},
  {"UpdatePointsAsmWithScale",   UpdatePointsAsmWithScale, 0},
  {"UpdatePointsAsmMovePointer", UpdatePointsAsmMovePointer, 0}
};
 
void InitPoints(MY_POINT *lpPoints, int nPointCount)
{
  int i;
  for (i = 0; i < nPointCount; i++)
  {
    lpPoints[i].x = i;
    lpPoints[i].y = 100 + i;
  }
}
 
int main()
{
  MY_POINT* lpPointsReference;
  MY_POINT* lpPoints;
  MY_POINT delta;
  DWORD nBeginning;
  DWORD nDuration;
  int nResult;
  int i, j, k;
 
  nResult = 1;
 
  lpPointsReference = (MY_POINT*)malloc(POINT_COUNT * sizeof(MY_POINT));
  if (!lpPointsReference)
  {
    puts("Malloc failed");
    goto the_end;
  }
  lpPoints = (MY_POINT*)malloc(POINT_COUNT * sizeof(MY_POINT));
  if (!lpPoints)
  {
    puts("Malloc failed");
    goto free_reference;
  }
 
  delta.x = 1;
  delta.y = 2;
 
  /* On fait une référence pour s'assurer des résultats des différentes fonctions */
  InitPoints(lpPointsReference, POINT_COUNT);
  UpdatePointsSimple(lpPointsReference, POINT_COUNT, &delta);
 
  /* On réalise plusieurs fois le test pour limiter les effets de bords */
  for (k = 0; k < TEST_COUNT; k++)
  {
    printf("*** Test %d ***\n", k);
 
    /* Pour toutes les fonctions à tester */
    for (i = 0; i < FUNCTION_TO_TEST_COUNT; i++)
    {
      InitPoints(lpPoints, POINT_COUNT);
      printf("Testing %s\n", updatePoints[i].name);
 
      nBeginning = GetTickCount();
      updatePoints[i].function(lpPoints, POINT_COUNT, &delta);
      nDuration = GetTickCount() - nBeginning;
      updatePoints[i].duration += nDuration;
      printf("%d\n", nDuration);
 
      /* Vérification du résultat */
      for (j = 0; j < POINT_COUNT; j++)
        if ((lpPointsReference[j].x != lpPoints[j].x) || (lpPointsReference[j].y != lpPoints[j].y))
        {
          puts("Difference between result and reference");
          goto free_points;
        }
    }
    puts("");
  }
  /* Affichage des temps moyens */
  for (i = 0; i < FUNCTION_TO_TEST_COUNT; i++)
  {
    printf("%s average duration = %d\n", updatePoints[i].name, updatePoints[i].duration / TEST_COUNT);
  }
  nResult = 0;
 
free_points:
  free(lpPoints);
free_reference:
  free(lpPointsReference);
the_end:
  return nResult;
}
rt15 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 28/01/2012, 19h54   #38
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 393
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : septembre 2005
Messages : 22 393
Points : 32 042
Points : 32 042
Envoyer un message via MSN à Médinoc
La page Wikipédia mentionne les préfixes de chaîne littérales pour Unicode.
J'espère qu'on va pouvoir les chaîner sans répéter sans arrêt le préfixe maintenant...

Edit: Oui enfin, on peut (Chapitre 6.4.5 "string literals", versets 5 et 9)
__________________
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone.
-- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Médinoc est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/07/2012, 14h38   #39
Médinoc
Expert Confirmé Sénior
 
Avatar de Médinoc
 
Homme
Développeur informatique
Inscription : septembre 2005
Messages : 22 393
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : septembre 2005
Messages : 22 393
Points : 32 042
Points : 32 042
Envoyer un message via MSN à Médinoc
News: Microsoft a confirmé il y a deux mois que les développeurs C99 pouvaient aller se faire voir.
__________________
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone.
-- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Médinoc est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/07/2012, 14h51   #40
Bktero
Expert Confirmé Sénior
 
Avatar de Bktero
 
Ingénieur systèmes embarqués
Inscription : juin 2009
Messages : 1 709
Détails du profil
Informations personnelles :
Âge : 25
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Ingénieur systèmes embarqués
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : juin 2009
Messages : 1 709
Points : 4 192
Points : 4 192
Si GCC a réussi à le faire, est-ce que c'est si compliqué pour Microsoft de le faire ?

J'ai du mal à comprendre pourquoi les gens (car malheureusement, ce n'est pas que Microsoft) restent bloqués au C ANSI, qui a plus de 20 ans.
__________________
Si Code::Blocks vous dit undefined reference to 'socket@12', cela signifie que vous avez un problème d'édition des liens. Allez dans Projects / Build Options / Linker Settings / Add et renseigner ici les .a qui vont bien. Exemple pour les sockets : C:\Program Files\CodeBlocks\MinGW\lib\libws2_32.a

Pour les adeptes du langage SMS, allez ici et ramenez la traduction française ^^

Pour vos problèmes d'embarqué, utilisez le forum dédié !
Bktero est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Actualité déjà publiée
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 04h06.


 
 
 
 
Partenaires

Hébergement Web