Python3 vs Python2.
c'est win2000 + python 2.7 au bureau, et ubuntu 10.04 + python 2.6 à la maison.
pour python 3, je vais attendre un peu.
>> Reste l'option du module C si c'est trop lent.
à +6 minutes par nuit, je peux faire l'impasse sur le C.
Python3 vs Python2.
c'est win2000 + python 2.7 au bureau, et ubuntu 10.04 + python 2.6 à la maison.
pour python 3, je vais attendre un peu.
>> Reste l'option du module C si c'est trop lent.
à +6 minutes par nuit, je peux faire l'impasse sur le C.
je ne sais pas si ça a été dejà posté ... la flemme de lire ^^
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 ma_chaine = 'azerty' ''.join(map(hex,bytearray(ma_chaine))).replace('0x','') ==> '617a65727479'
Je n'ai pas lu toute la discussion, juste les derniers posts, mais quand j'ai un tas de strings à concaténer, je les mets dans une liste ou et je fais un ''.join dessus à la fin. C'est simple et efficace.
Dans ce cas-ci on dirait qu'on peut même faire '$'.join(...)
[EDIT] Oops j'avais pas vu qu'il y avait une seconde page ^^. Déjà proposé par josmiley. Enfin on parle peut-être pas tout à fait de la même chose.
Au lieu de
"".join( [x for x in .....] )
on peut écrire
"".join( x for x in ........ )
À la place de
il y avait aussi
Code : Sélectionner tout - Visualiser dans une fenêtre à part lambda nb:''.join([hex(ord(i)).strip('0x').rjust(2, '0') for i in nb])
Code : Sélectionner tout - Visualiser dans une fenêtre à part lambda nb:''.join([hex(ord(i))[2:].zfill(2) for i in nb])
La fonction comp3() dans le message #4 arrive comme un cheveu dans la soupe: on se demande pourquoi comp3( chr(0x00) ) donne ’00’ et pourquoi comp3( chr(0x3d) ) donne un signe à l’ensemble.
C’est ton algo qui est comme ça, mais ça surprend.
time.clock()
On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of "processor time", depends on that of the C function of the same name, but in any case, this is the function to use for benchmarking Python or timing algorithms.
On Windows, this function returns wall-clock seconds elapsed since the first call to this function, as a floating point number, based on the Win32 function QueryPerformanceCounter(). The resolution is typically better than one microsecond.
http://docs.python.org/library/time.html
À chaque tour de l’itération , l’interpréteur est obligé d’aller chercher dans binsacii la fonction hexlify() . C’est perdre du temps pour rien.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 import binascii while 1: ............... inHex = binascii.hexlify(inChr)
Importer la fonction hexlify() dans l’espace de noms global avec from binascci import hexlify
la rend directement disponible et élimine une perte de temps répétitive.
Bien vu !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 print a.encode("hex") '6d657373616765'
Je ne connaissais pas cette utilisation des fonctions encode() et decode() avec ce codec et ses camarades.
Dommage que ce soit plus lent.
C’est sûr !!out = ''
out += trt_pack(inHex[0:6]) #iavo
out += "$"
out += trt_date(inHex[6:15]) #dins
out += "$"
out += inChr[8:9] #cins
out += "$"
....................
Avec autant de concaténations, pas étonnant que ça prenne beaucoup de temps.
Pour concaténer, il y a deux méthodes lentes:
+= et formatage avec %,
et deux méthodes rapides:
+ et join()
Et il y a d’autre choses étonnantes.
"".ljust(10, ' ') dans la fonction trt_date(d) est assez cocasse.
La fonction trt_packdec() créée pour deux utilisations seulement
trt_packdec(inHex[66:74], 4)
et trt_packdec(inHex[74:82], 2)
dont on s’aperçoit qu’elles sont simplifiables ,
est aussi un marteau-piqueur pour écraser deux noisettes. Un appel de fonction est coûteux en temps, celle -ci juste pour faire du calcul d’indice.
J’ai donc simplifié.
J’ai aussi remplacé la fonction trt_pack() par un dictionnaire qui donne le signe en un clin d’œil.
Je suis d’accord. Donc, application: lecture du fichier 'packed_file' par gros morceaux de 4700 caractères et plus, traités en entier avant qu’il y ait écriture.Il est plus rapide de travailler en mémoire et d'écrire les fichiers par bloc.
4700 est une valeur minime. En fonction des possibilités de la machine sur laquelle ça tournera, ce nombre pourra être augmenté. Il faudra rechercher la valeur optimale.
Enfin, comme le temps d’exécution dépend fortement de l’algorithme plutôt que des astuces trouvées dans la manière d’écrire un code , il faut à mon avis modifier la construction de out en évitant des opérations inutiles de concaténation.
J’ai un peu modifié ton code, avi3000, pour mener des tests (fonction clock, nombre nn de z écrits...) mais pas son algorithme.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 #!/usr/bin/env python # -*- coding:UTF-8 -*- """ conversion de la table ACT """ from time import clock import binascii def trt_act(): """ création du fichier étendu 200 000 records, 20 Mo """ i = 0 inFile = open('packed_file', 'r') outFile = open('mis_a_plat', 'w') while 1: inChr = inFile.read(47) if inChr == '' : break inHex = binascii.hexlify(inChr) out = '' out += trt_pack(inHex[0:6]) #iavo out += "$" out += trt_date(inHex[6:15]) #dins out += "$" out += inChr[8:9] #cins out += "$" out += trt_date(inHex[18:27]) #dces out += "$" out += inChr[14:15] #cces out += "$" out += trt_pack(inHex[30:34]) #iban out += "$" out += inChr[17:20] #natv out += "$" out += inChr[20:21] #catv out += "$" out += trt_pack(inHex[42:48]) #istr out += "$" out += trt_pack(inHex[48:52]) #qann out += "$" out += trt_pack(inHex[52:56]) #qmoi out += "$" out += trt_pack(inHex[56:60]) #qjou out += "$" out += trt_pack(inHex[60:66]) #cpay out += "$" out += trt_packdec(inHex[66:74], 4) #qexe out += "$" out += trt_packdec(inHex[74:82], 2) #qex2 out += "$" out += inChr[41:42] #ccer out += "$" out += trt_date(inHex[84:93]) #dmaj outFile.write(out + '\n') inFile.close(), outFile.close(); def trt_pack(s): """ traitement des entiers """ if s[-1] == 'f' : return '+' + s[:-1] elif s[-1] == 'd' : return '-' + s[:-1] else : return '%' + s[:-1] def trt_packdec(s, d): """ traitement des nombres décimaux """ if s[-1] == 'f' : sign = '+' elif [-1] == 'd' : sign = '-' else : sign = '%' return sign + s[:len(s)-d-1] + ',' + s[len(s)-d-1:-1] def trt_date(d): """ traitement des dates """ aaaa = d[1:5] mm = d[5:7] jj = d[7:] if aaaa == '0000' : return ''.ljust(10, ' ') elif mm == '00' or jj == '00' : return '01/01/' + aaaa else : return jj + '/' + mm + '/' + aaaa def create_act(nn): """ création du fichier de test 200 000 records, 9 Mo """ z = chr(0x00) + chr(0x00) + chr(0x1f) #iavo z += chr(0x01) + chr(0x94) + chr(0x60) + chr(0x41) + chr(0x2f) #dins z += 'S' #cins z += chr(0x00) + chr(0x00) + chr(0x00) + chr(0x00) + chr(0x0f) #dces z += ' ' #cces z += chr(0x10) + chr(0x5f) #iban z += '511' #natv z += '5' #catv z += chr(0x29) + chr(0x00) + chr(0x3f) #istr z += chr(0x03) + chr(0x8f) #qann z += chr(0x02) + chr(0x6f) #qmoi z += chr(0x01) + chr(0x2f) #qjou z += chr(0x10) + chr(0x23) + chr(0x1f) #fill z += chr(0x03) + chr(0x82) + chr(0x61) + chr(0x2f) #qexe z += chr(0x03) + chr(0x72) + chr(0x61) + chr(0x2f) #qex2 z += 'C' #ccer z += chr(0x02) + chr(0x00) + chr(0x31) + chr(0x22) + chr(0x5f) #dmaj i = 0 outFile = open('packed_file', 'w') while i < nn: outFile.write(z) i += 1 outFile.close() return len(z) #============= if __name__ == "__main__": import os os.system('clear') #for nn in (1000,2000,4000,8000,16000,32000,100000): for nn in (200000,): print 'nn = '+str(nn)+ ' code avi3000' licreate,liunpack = [],[] for fois in xrange(3): t1 = clock() lenz = create_act(nn) dt1 = clock() - t1 licreate.append(dt1) min_create = min(licreate) for u in xrange(20): t1 = clock() trt_act() dt2 = clock() - t1 liunpack.append(dt2) print str(lenz)+' create (minimum) : ' + str(min_create)[0:8]+\ ' unpack : ' + str(dt2)[0:8]+\ ' ratio : '+str(dt2/min_create)[0:5] #print 'ghgh' + 'éèàù' print 24*' '+'MINIMUM ~~ unpack = '+ str(min(liunpack))[0:8]+\ ' ~~ ratio = '+ str(min(liunpack)/min_create)[0:5]+'\n'
J’avais d’abord fait un code sans lecture par morceaux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 #!/usr/bin/env python # -*- coding:UTF-8 -*- """ conversion de la table ACT """ from time import clock from binascii import hexlify from os.path import getsize def create_act(nn): """ création du fichier de test 200 000 records, 9 Mo """ z = (chr(0x00) , chr(0x00) , chr(0x1f) , chr(0x01) , chr(0x94) , chr(0x60) , chr(0x41) , chr(0x2f) , #dins 'S' , chr(0x00) , chr(0x00) , chr(0x00) , chr(0x00) , chr(0x0f) , #dces ' ' , chr(0x10) , chr(0x5f) , #iban '5115' , chr(0x29) , chr(0x00) , chr(0x3f) , #istr chr(0x03) , chr(0x8f) , #qann chr(0x02) , chr(0x6f) , #qmoi chr(0x01) , chr(0x2f) , #qjou chr(0x10) , chr(0x23) , chr(0x1f) , #fill chr(0x03) , chr(0x82) , chr(0x61) , chr(0x2f) , #qexe chr(0x03) , chr(0x72) , chr(0x61) , chr(0x2f) , #qex2 'C' , chr(0x02) , chr(0x00) , chr(0x31) , chr(0x22) , chr(0x5f)) #dmaj z = ''.join(z) with open('packed_file47', 'w') as outFile: for i in xrange(nn): outFile.write(z) return len(z) def trt_act(): """ création du fichier étendu 200 000 records, 20 Mo """ pack = {}.fromkeys('0123456789abc','%') pack['d'] = '-' pack['f'] = '+' def trt_date(d): """ traitement des dates """ if d[1:5] == '0000' : return ' ' elif d[5:7] == '00' or d[7:] == '00' : return '01/01/' + d[1:5] else : return d[7:] + '/' + d[5:7] + '/' + d[1:5] with open('packed_file47', 'r') as inFile, open('mis_a_plat47', 'w') as outFile: inChr = inFile.read(47) while len(inChr): inHex = hexlify(inChr) out = (pack[inHex[5]] + inHex[0:5], #iavo trt_date(inHex[6:15]), #dins inChr[8], #cins trt_date(inHex[18:27]), #dces inChr[14], #cces pack[inHex[33]] + inHex[30:33], #iban inChr[17:20], #natv inChr[20:21], #catv pack[inHex[47]] + inHex[42:47], #istr pack[inHex[51]] + inHex[48:51], #qann pack[inHex[55]] + inHex[52:55], #qmoi pack[inHex[59]] + inHex[56:59], #qjou pack[inHex[65]] + inHex[60:65], #cpay pack[inHex[73]] + inHex[66:69] + ',' + inHex[69:73], #qexe pack[inHex[81]] + inHex[74:79] + ',' + inHex[79:81], #qex2 inChr[41], #ccer trt_date(inHex[84:93]) + '\n') #dmaj outFile.write('$'.join(out)) inChr = inFile.read(47) #============= if __name__ == "__main__": import os os.system('clear') #for nn in (1000,2000,4000,8000,16000,32000,100000): for nn in (200000,): print 'nn = ' + str(nn) + ' lecture par 47 octets' licreate = [] liunpack = [] for fois in xrange(3): t0 = clock() lenz = create_act(nn) dt1 = clock() - t0 licreate.append(dt1) min_create = min(licreate) for u in xrange(20): t0 = clock() trt_act() dt2 = clock() - t0 liunpack.append(dt2) print str(lenz)+' create (minimum) : ' + str(min_create)[0:8]+\ ' unpack : ' + str(dt2)[0:8]+\ ' ratio = '+str(dt2/min_create)[0:5] #print 'ghgh' + 'éèàù' print 24*' '+'MINIMUM ~~ unpack = '+ str(min(liunpack))[0:8]+\ ' ~~ ratio = '+ str(min(liunpack)/min_create)[0:5]+'\n'
Et finalement j’ai aussi réécrit le code pour faire la lecture de ’packed_file’ par morceaux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 #!/usr/bin/env python # -*- coding:UTF-8 -*- """ conversion de la table ACT """ from time import clock from binascii import hexlify from os.path import getsize def trt_act(taille_chunk): """ création du fichier étendu 200 000 records, 20 Mo """ pack = {}.fromkeys('0123456789abc','%') pack['d'] = '-' pack['f'] = '+' def trt_date(d): """ traitement des dates """ if d[1:5] == '0000' : return ' ' elif d[5:7] == '00' or d[7:] == '00' : return '01/01/' + d[1:5] else : return d[7:] + '/' + d[5:7] + '/' + d[1:5] def outing(inChunk): for k in xrange(0,len(inChunk), 47): inHex = hexlify(inChunk[k:k+48]) yield '$'.join((pack[inHex[5]] + inHex[0:5], #iavo trt_date(inHex[6:15]), #dins inChunk[k+8], #cins trt_date(inHex[18:27]), #dces inChunk[k+14], #cces pack[inHex[33]] + inHex[30:33], #iban inChunk[k+17:k+20], #natv inChunk[k+20:k+21], #catv pack[inHex[47]] + inHex[42:47], #istr pack[inHex[51]] + inHex[48:51], #qann pack[inHex[55]] + inHex[52:55], #qmoi pack[inHex[59]] + inHex[56:59], #qjou pack[inHex[65]] + inHex[60:65], #cpay pack[inHex[73]] + inHex[66:69] + ',' + inHex[69:73], #qexe pack[inHex[81]] + inHex[74:79] + ',' + inHex[79:81], #qex2 inChunk[k+41], #ccer trt_date(inHex[84:93]) + '\n')) #dmaj with open('packed_file'+str(taille_chunk), 'r') as inFile: with open('mis_a_plat'+str(taille_chunk), 'w') as outFile: inChunk = inFile.read(taille_chunk) while len(inChunk): outFile.write(''.join(line for line in outing(inChunk))) inChunk = inFile.read(taille_chunk) def create_act(nn): """ création du fichier de test nn records, ~9 Mo si nn = 200000""" z = (chr(0x00) , chr(0x00) , chr(0x1f) , chr(0x01) , chr(0x94) , chr(0x60) , chr(0x41) , chr(0x2f) , #dins 'S' , chr(0x00) , chr(0x00) , chr(0x00) , chr(0x00) , chr(0x0f) , #dces ' ' , chr(0x10) , chr(0x5f) , #iban '5115' , chr(0x29) , chr(0x00) , chr(0x3f) , #istr chr(0x03) , chr(0x8f) , #qann chr(0x02) , chr(0x6f) , #qmoi chr(0x01) , chr(0x2f) , #qjou chr(0x10) , chr(0x23) , chr(0x1f) , #fill chr(0x03) , chr(0x82) , chr(0x61) , chr(0x2f) , #qexe chr(0x03) , chr(0x72) , chr(0x61) , chr(0x2f) , #qex2 'C' , chr(0x02) , chr(0x00) , chr(0x31) , chr(0x22) , chr(0x5f)) #dmaj z = ''.join(z) with open('packed_file'+str(taille_chunk), 'w') as outFile: for i in xrange(nn): outFile.write(z) return len(z) #============= if __name__ == "__main__": import os os.system('clear') taille_chunk = 940000 #for nn in (1000,2000,4000,8000,16000,32000,100000): for nn in (200000,): print 'nn = ' + str(nn) + ' lecture par morceaux de '+str(taille_chunk)+' octets' licreate,liunpack = [],[] for fois in xrange(3): t0 = clock() lenz = create_act(nn) dt1 = clock() - t0 licreate.append(dt1) min_create = min(licreate) for u in xrange(20): t0 = clock() trt_act(taille_chunk) dt2 = clock() - t0 liunpack.append(dt2) print str(lenz)+' create (minimum) : ' + str(min_create)[0:8]+\ ' unpack : ' + str(dt2)[0:8]+\ ' ratio : '+str(dt2/min_create)[0:5] #print 'ghgh' + 'éèàù' print 24*' '+'MINIMUM ~~ unpack = '+ str(min(liunpack))[0:8]+\ ' ~~ ratio = '+ str(min(liunpack)/min_create)[0:5]+'\n'
----------------------------------------------
J’ai mené des tests avec
for nn in (1000,2000,4000,8000,16000,32000,100000):
mais les résultats sont assez surprenants.
nn est le nombre de z écrits dans ’packed_file’ dans la partie create()
Je pensais que le ratio temps d’exécution de unpack/temps d’exécution de create évoluerait d’une manière continue avec nn, plutôt à la hausse, et que cette variation serait différente selon le code.
Mais pour un même code, il y a une variation bizarre du ratio, sans liaison avec la valeur de nn, mais identique avec les 3 programmes ! : le ratio augmente d’environ 60 % de nn = 1000 à nn = 2000 et 4000, puis il augmente un peu pour nn = 8000, 16000, 32000, puis pouf ! il retombe fortement pour nn = 100000, à une valeur qui est même en dessous de la valeur du ratio pour nn = 1000 !!
Je n’y comprends rien. Mais je pense que ce n’est pas le plus intéressant.
-----------------------------------------------------
Je me suis donc intéressé exclusivement aux temps de unpack pour nn = 200000 que j'ai comparé entre eux.
J'ai fait en sorte de trouver d'abord le temps minimal de création de 'packed_file' (il devrait logiquement être assez constant mais ce n’est pas tout à fait le cas) et j'ai fait répéter plusieurs fois l'exécution de trt_act() pour extraire le temps minimal parmi les divers essais.
J'ai comparé les temps minimaux obtenus sur les 3 programmes car ils sont plus significatifs des performances les meilleures que peuvent avoir des programmes quand ils ne sont pas gênés par des événements ordinateurs parasitant le CPU.
PGavi :
celui du message #11 avec les fonctions trt_date(d) , trt_packdec(s, d) , trt_pack(s) , et des concaténations +=
PGey1 :
avec lecture de ’'packed_file47' par 47 octets, tuple out et outFile.write('$'.join(out)) , dictionnaire pack à la place de la fonction trt_pack(s) , disparition de la fonction trt_packdec(s, d)
PGey2 :
avec lecture de ’'packed_file4700' par morceaux inChunk de 4700,47000,94000 octets, fonction génératrice renvoyant un ’$’.join(out) , dans out utilisation de pack au lieu de trt_pack(s) et plus de trt_packdec(s, d) comme dans PGey1.
NB: j’ai vérifié mes codes PGey en comparant les fichiers ’mis_a_plat’ obtenus par eux avec le fichier obtenu par ton code PGavi. C’est identique.
Résultats, pour nn = 200000
PGey1 / PGavi = 61,9 %
PGey2 / PGavi = 58,2 % avec taille_chunk = 4700
PGey2 / PGavi = 55,6 % avec taille_chunk = 47000
PGey2 / PGavi = 53,3 % avec taille_chunk = 94000
Mon ordi était très lent, les valeurs absolues n’auraient aucun intérêt.
Dîtes moi si vous retrouvez la même baisse de temps d’exécution sur vos machines, svp.
Je pensais que la différence serait plus importante de PGey1 à PGey2, c’est à dire que la lecture par morceaux (donc et surtout écriture par grands morceaux aussi) apporterait une augmentation de la rapidité déjà constatée avec PGey1 par rapport à PGavi.
Mais la lecture et l’écriture par morceaux n’a pas tant d’influence que ça.
-----------------------------
Je pense qu'on pourrait encore creuser les choses pour trouver des optimisatiions supplémentaires.
Il y en a une notamment dans la fonction trt_date(d):
si les fichiers sont tels qu’on y rencontre le plus souvent des aaaa == '0000' ,
la place de if aaaa == '0000' : est alors bien en premier.
Mais si les dates sont le plus souvent normales, il faut mettre
en premier.
Code : Sélectionner tout - Visualiser dans une fenêtre à part if aaaa!='0000' and mm!='00' and jj!='00':
Et pousser ausi la recherche d’optimisation en tenant compte de ce qui se passe avant et après les 6 mnn (maintenant 3mn30) de conversion.
PS:
Comme on fait ’$’.join(...) , je me dis que ces ’$’ sont sans doute en rapport avec l’écriture $var des variables en PHP.
À quoi sert PHP dans l’histoire ? Pourquoi garder un tel canard boiteux ? Je suis sûr que Python arriverait à remplir sa tâche aussi bien.Je profite du changement de serveur pour basculer les traitements VB98 vers python et PHP.
Bonjour,
Eyquem a posté beaucoup de choses, donc du bon et du moins bon.
petits rappels:
l'exemple qui est donné concerne un fichier (une table) sur 250.
L'écriture d'une fonction peu utilisée dans l'exemple, l'est forcément plus dans l'ensemble du traitement.
L'utilisation de fonctions est un compromis entre la lisibilité du programme et ses performances.
La version du code utilisé le 7 août était celle du #19.
Le bon : PGey1
La concaténation par tuple out et outFile.write('$'.join(out)) est plus rapide de 16-18% par rapport aux autres méthodes.
La reconnaissance du signe par indirection via le dictionnaire est 10% plus rapide que la version avec if-else, mais c'est négligeable.
L'intérêt principal du dictionnaire est de pouvoir supprimer des appels de fonction et de remonter la détermination du signe dans le corps du programme sans altérer la lisibilité.
En appliquant ces 2 méthodes, le temps d'exécution est passé de 6 à 4,1 secondes.
Le moins bon :
PGey2, on utilisait ce mode de lecture par blocs d'enregistrement il y a une trentaine d'années, mais c'était totalement transparent au niveau du code.
La lecture enregistrement par enregistrement ou tout le fichier d'un coup me paraissent de meilleures solutions.
>>"".ljust(10, ' ') dans la fonction trt_date(d) est assez cocasse.
Si tu as mieux, je suis preneur.
>>je me dis que ces ’$’ sont sans doute en rapport avec l’écriture $var des variables en PHP.
pas du tout, j'utilise fréquemment le $ ou la £ comme délimiteurs de champs.
>>À quoi sert PHP dans l’histoire ? Pourquoi garder un tel canard boiteux ? Je suis sûr que Python arriverait à remplir sa tâche aussi bien.
C'est possible, mais on fait comme on peut et avec ce qu'on a.
Si la documentation francophone de Python était à la hauteur de celle du PHP, je serais peut-être d'un autre avis.
Pour l'heure j'utilise les deux en fonction de mes humeurs. En l'espèce les 250 programmes Python sont générés par du code PHP.
J'allais oublier : merci pour le bon.
Tu veux dire que parce qu’une fonction sera plus utilisée dans l’ensemble, ça vaut la peine de garder des actions sous forme de fonction pour raison de lisibilité ?l'exemple qui est donné concerne un fichier (une table) sur 250.
L'écriture d'une fonction peu utilisée dans l'exemple, l'est forcément plus dans l'ensemble du traitement.
L'utilisation de fonctions est un compromis entre la lisibilité du programme et ses performances.
Ce n’est pas mon avis.
- Si un appel de fonction est mange-temps (je ne suis pas sûr que ce soit tout le temps le cas, je reste prudent), et que l’objectif est de réduire le temps d’exécution, alors a-t-on vraiment le choix ?
- Pour moi, des petits bouts de fonction comme trt_packdec(s, d) et trt_date(d) entravent plus la perception globale d’un code qu’ils n'assurent sa lisibilité.
- L’absence d’une fonction peut être compensée par des commentaires plus nombreux et fournis dans tout le code.
- On ne regarde pas un code tout les jours. Rendre un programme plus lent au prétexte qu’on veut le comprendre plus rapidement quand on le regardera épisodiquement ne tient pas la route, de mon point de vue. Python a une syntaxe claire qui est propice à une meilleure maintenabilité que dans d’autres langages. il faut arriver à se défaire des mauvaises habitudes prises avec les autres langages.
Mais ce n’est que mon avis personnel à moi.
Je ne comprends pas. Le 7 août, il y a eu un post, de moi, et dans les codes présentés il n’y a pas de recours à memoryview qu'il y a dans #19La version du code utilisé le 7 août était celle du #19.
Tu trouves que 10 % c’est négligeable mais pas 16-18 %La concaténation par tuple out et outFile.write('$'.join(out)) est plus rapide de 16-18% par rapport aux autres méthodes.
La reconnaissance du signe par indirection via le dictionnaire est 10% plus rapide que la version avec if-else, mais c'est négligeable.
Ah, tu partages l'idée qu'éliminer des appels de fonction a de l'intérêt.L'intérêt principal du dictionnaire est de pouvoir supprimer des appels de fonction et de remonter la détermination du signe dans le corps du programme sans altérer la lisibilité.
Cela fait -31 % , presque un tiers de temps en moins.Pourtant en appliquant ces 2 méthodes, le temps d'exécution est passé de 6 à 4,1 secondes.
Mais 16-18 % + 10 % = 26-28 % . Même si 10 % est peu d’après toi, l’apport du dictionnaire amplifie le bénéfice de l’autre modif.
Comprends pas.PGey2, on utilisait ce mode de lecture par blocs d'enregistrement il y a une trentaine d'années, mais c'était totalement transparent au niveau du code.
Tu veux dire que ce programme tournait déjà il y a 30 ans dans votre entreprise ? Ou que c’est une technique dépassée ? Pourquoi serait ce à bannir pour cause d’ancienneté, si ça accélère l’exécution ?
« totalement transparent au niveau du code » , ça veut dire quoi ?
Pourquoi ?La lecture enregistrement par enregistrement ou tout le fichier d'un coup me paraissent de meilleures solutions.
>>"".ljust(10, ' ') dans la fonction trt_date(d) est assez cocasse.
Si tu as mieux, je suis preneur.La dernière formule se trouve d’ailleurs dans mes codes, car c’est celle que je préfère.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 print 'A' + ''.ljust(10, ' ') + 'Z' print 'A' + '%-10s' % ' ' + 'Z' print 'A' + 10*' ' + 'Z' print 'A' + ' ' + 'Z'
Par hauteur, il faut entendre quantité je présume, car pour ce qui est de la qualité, celle de la doc de Python est à mon sens bien meilleure que celle de la filandreuse doc de PHP.>>À quoi sert PHP dans l’histoire ? Pourquoi garder un tel canard boiteux ? Je suis sûr que Python arriverait à remplir sa tâche aussi bien.
C'est possible, mais on fait comme on peut et avec ce qu'on a.
Si la documentation francophone de Python était à la hauteur de celle du PHP, je serais peut-être d'un autre avis.
Pour ce qui est de Python, tu as raison, il semble n’y avoir aucune doc exhaustive et à la page en français. C’est un mauvais point.
Des programmes Python générés par du PHP ? Il doit y avoir quelque chose qui m’a échappé.En l'espèce les 250 programmes Python sont générés par du code PHP.
--------------------------------------------------------------
D’autre part, la réapparition de cette file me fait penser que j’ai oublié de poster un code qui améliore encore la vitesse d’exécution qui est passée en dessous de 50 % par rapport au premier code du message #24 qui est claqué sur un code de avi3000.
Les changements:
- pack = dict(zip('0123456789abcdef','%%%%%%%%%%%%%-%+'))
comme argument par défaut : la création de l’objet dictionnaire pack n’est faite qu’une fois.
À chacun des appels de trt_act() sur les 255 fichiers après le premier traité, pack existe déjà et n’est pas recréé.
Ce n’est pas ça qui va influer sur la vitesse mais bon....
Et ce qui est susceptible d’augmenter la vitesse d’exécution:
- def trt_date(aaaa,mm,jj) au lieu de def trt_date(d)
- dans PGey2,
on fournit un morceau de fichier inChunk qui est passé comme argument à outing(inChunk) , fonction dans laquelle inChunk est transformé en hexadécimal par segments de 47 octets pour produire des objets inHex
Idée: faire la transformation de inChunk en hexadécimal une seule fois et itérer en obtenant les inHex par découpage du résultat de la transformation
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 for k in xrange(0,len(inChunk), 47): inHex = hexlify(inChunk[k:k+48])
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 inHexTot = hexlify(inChunk) def outing(inChunk, inHexTot, datage = trt_date): for k in xrange(0,len(inChunk), 47): inHex = inHexTot[2*k:2*k+94]
- j’ai choisi de calculer inHexTot dans le while , a l’extérieur de outing() , et de le passer en argument à outing()
au lieu de passer inChunk à outing() et de calculer inHexTot dans outing() :
il n’y a pas de raison déterminante pour l’une ou l’autre possibilité.
Elles sont à mon avis équivalentes, il faut dans les deux cas passer un objet en arguments.
Par contre, dans l’une ou l’autre possibilité, il est préférable de passer la donnée inChunk ou inHexTot en argument à outing() :
cela évite à outing() de chercher cet objet à l’extérieur de son espace de nom
Passé en argument, c’est en fait l’adresse qui est passée: outing() sait alors tout de suite où aller chercher la donnée en mémoire.The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names.
http://docs.python.org/tutorial/cont...ning-functions
- dans le même ordre d’idée, en passant la fonction trt_date() en argument à outing() , on lui évite de devoir à chaque fois aller la chercher à l’extérieur d’elle.
Concernant ces deux derniers points, je crois que le fait que outing() est une fonction génératrice ne change rien au fait que si un objet situé à l’extérieur est utilisé dans la fonction, elle est obligée d’aller le chercher dans l'espace de noms extérieur: c’est un objet libre et qui reste libre, et non pas un objet défini dans la fonction et qui serait à ce titre enregistré dans l’espace de nom local.
If a variable is used in a code block but not defined there, it is a free variable.
http://docs.python.org/reference/exe...ng-and-binding
- enfin le plus déterminant sur la vitesse est de remplacer
outFile.write(''.join(line for line in outing(....)))
par
outFile.write(''.join(outing(....)))
Étonnant.
Résultats, pour nn = 200000
PGey3 / PGavi = 47,5 % avec taille_chunk = 47000
PGey3 / PGavi = 47,1 % avec taille_chunk = 94000
Sur la base des temps minimaux, car ce sont ceux qui représentent le mieux la célérité intrinsèque d’un programme.
J’ai aussi essayé deux idées supplémentaires:
- fixer le buffering à 0:
- traiter des morceaux inChunk qui soient des multiples de 128,264,512,1024,2048,4096... etc
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 with open('packed_file'+str(taille_chunk), 'r', 0) as inFile, \ open('mis_a_plat'+str(taille_chunk), 'w', 0) as outFile:
en fixant taille_chunk par exemple à 47 x 1024
Je n’ai constaté aucun accroissement de vitesse en les mettant en application.
------------------------------------------------
Il y a d’autres pistes à explorer pour diminuer encore le temps d’exécution:
http://psyco.sourceforge.net/
http://cython.org/
http://www.scipy.org/Weave
http://python.net/crew/theller/ctypes/
http://docs.python.org/library/ctypes.html
en français:
http://wikipython.flibuste.net/Ctypes
mais je vais te laisser faire car je ne connais rien à ces modules.
Bonjour,
J'ai une chaîne de 4 caractères contenant un entier que je dois convertir.
Les containtes de performance sont à prendre en compte.
J'ai codé comme ci-dessous, mais si vous avez mieux ou plus beau,
je suis preneur.
Merci
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 n = 20000 nb = '\x00\x01\x01\x01' t1 = time() i = 0 for fois in xrange(n): i = 0 for j in xrange(4) : i += ord(nb[j]) * (256**(3-j)) z = str(i) print 'z='+ z 65793 #ce qui est vrai et juste print 'trt 1: ' + str(time() - t1) trt : 16.78799
Il serait sage de dire ce qu'on doit faire et mesurer car les 2 petites modifications ci dessous améliorent sensiblement les choses...
Mais çà dépend de ce qu'on veut mesurer.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 n = 20000 nb = '\x00\x01\x01\x01' t1 = time() #i = 0 for fois in xrange(n): i = 0 for j in xrange(4) : i += ord(nb[j]) * (256**(3-j)) #z = str(i) z = str(i) print 'z='+ z 65793 #ce qui est vrai et juste print 'trt 1: ' + str(time() - t1) trt : 16.78799
Pourquoi ne pas reformuler cela sous la forme d'une fonction avec les paramètres d'entrées et de sortie sont une bonne "bordure" pour çà.
- W
La demande ne portait que sur la partie de code ci-dessous.
Le reste ne sert que pour les tests et ne présente aucun intérêt.
la fonction :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 nb = '\x00\x01\x01\x01' i = 0 for j in xrange(4) : i += ord(nb[j]) * (256**(3-j)) z = str(i)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 def trt_bin(b): """ traitement des binaires""" i = 0 for j in xrange(4) : i += ord(b[j]) * (256**(3-j)) return str(i)
pas beaucoup plus performant(1,4 fois plus rapide quand même) mais moins tordu
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 nb = 'abcd' i=0 for j in nb: i=(i<<8)+ord(j) z = str(i)
time.clock()
On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of “processor time”, depends on that of the C function of the same name, but in any case, this is the function to use for benchmarking Python or timing algorithms.
On Windows, this function returns wall-clock seconds elapsed since the first call to this function, as a floating point number, based on the Win32 function QueryPerformanceCounter(). The resolution is typically better than one microsecond.
S’il n’y a toujours que 4 chiffres dans le nombre nb .... :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 from time import clock from binascii import hexlify n = 2000 nb = '\x05\x3A\x01\xDE' print "ord('\\xff') = ",ord('\xff') print 'nb =',''.join(map(lambda u: '\\'+'x'+hexlify(u), nb)) print avi,A,B,C,D,E = [],[],[],[],[],[] rep = 50 #---------------------------------------------- for repet in xrange(rep): t0 = clock() for fois in xrange(n): i = 0 for j in xrange(4) : i += ord(nb[j]) * (256**(3-j)) avi.append(clock()-t0) print 'i =',i,' avi' #---------------------------------------------- deek = {3:1,2:256,1:65536,0:16777216} for repet in xrange(rep): t0 = clock() for fois in xrange(n): i = sum( ord(nb[j]) * deek[j] for j in xrange(4) ) A.append(clock()-t0) print 'i =',i,' A' #---------------------------------------------- deek = {3:1,2:256,1:65536,0:16777216} for repet in xrange(rep): t0 = clock() for fois in xrange(n): i = 0 for j in xrange(4) : i += ord(nb[j]) * deek[j] B.append(clock()-t0) print 'i =',i,' B' #---------------------------------------------- for repet in xrange(rep): t0 = clock() for fois in xrange(n): i = 0 for (m,u) in ((16777216,nb[0]),(65536,nb[1]),(256,nb[2]),(1,nb[3])): i += ord(u) * m C.append(clock()-t0) print 'i =',i,' C' #---------------------------------------------- for repet in xrange(rep): t0 = clock() for fois in xrange(n): i = 16777216*ord(nb[0]) + 65536*ord(nb[1]) + 256*ord(nb[2]) + ord(nb[3]) D.append(clock()-t0) print 'i =',i,' D' #---------------------------------------------- def treat_bin(nb): return 16777216*ord(nb[0]) + 65536*ord(nb[1]) + 256*ord(nb[2]) + ord(nb[3]) for repet in xrange(rep): t0 = clock() for fois in xrange(n): i = treat_bin(nb) E.append(clock()-t0) print 'i =',i,' E' #=============================================== print '\n secondes' print ' ',str(min(avi))[0:8],' code de reference avi ' print ' -------- ----------------------------------------------' print 'A ',str(min(A))[0:8],' sum( ord(nb[j]) * deek[j] for j in xrange(4) )' print 'B ',str(min(B))[0:8],' i += ord(nb[j]) * deek[j]' print 'C ',str(min(C))[0:8],' for (m,u) in ((16777216,nb[0]),......)' print 'D ',str(min(D))[0:8],' i = 16777216*ord(nb[0]) + 65536*ord(nb[1])....' print 'E ',str(min(E))[0:8],' i = treat_bin(nb)'
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 ord('\xff') = 255 nb = \x05\x3a\x01\xde i = 87687646 avi i = 87687646 A i = 87687646 B i = 87687646 C i = 87687646 D i = 87687646 E secondes 0.039467 code de reference avi -------- ---------------------------------------------- A 0.038304 sum( ord(nb[j]) * deek[j] for j in xrange(4) ) B 0.037361 i += ord(nb[j]) * deek[j] C 0.032957 for (m,u) in ((16777216,nb[0]),......) D 0.014271 i = 16777216*ord(nb[0]) + 65536*ord(nb[1]).... E 0.013791 i = treat_bin(nb)
J'ai fixé n à 2000 parce que mon ordinateur est lent.
Par ailleurs, est-ce que tu as vu mon message #26 posté depuis ton dernier passage ?
Quelques petites améliorations dans mon code ont fait descendre le temps d’exécution à 47 % du temps de ton code initial.
mon dernier mot:
on déplie et on accélère via locals
comparé à l'orginal qui chez moi donne
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 M = [ 24, 16, 8, 1] def trt_bin(b): """ traitement des binaires""" lord = ord m = M r = (lord(b[0]) << M[0]) + (lord(b[1]) << M[1]) + (lord(b[2]) << M[2]) + (lord(b[3]) << M[3]) return str(r)
il sort:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 z= 65793 trt_bin_1: 0.091716 s.
- W
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 z= 65793 trt_bin_x: 0.053163 s.
je suppose que c'est:
et non:
Code : Sélectionner tout - Visualiser dans une fenêtre à part M = [ 24, 16, 8, 0]
Code : Sélectionner tout - Visualiser dans une fenêtre à part M = [ 24, 16, 8, 1]
effectivement, si la longueur de la chaine est constante ...
mais le code de wiztricks est plus rapide.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 def trt_bin(b): a,b,c,d=bytearray(b) return str((a<<24)+(b<<16)+(c<<8)+d)
ord() est plus rapide que bytearray
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 def trt_bin(b): return str((ord(b[0])<<24)+(ord(b[1])<<16)+(ord(b[2])<<8)+ord(b[3]))
Salut,
A la réflexion, c'est quand même un peu dommage de faire tout çà alors que
int('0x00010101', 16) ferait faire ces mêmes opérations plus près du processeur.
A défaut de pouvoir remplacer les arguments reçus, comment faire proche de... avec struct unpack çà donne:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 def trt_bin_6(b, l=unpack, s=str): return s(l('>L',nb)[0]) def trt_bin_61(b): return str(unpack('>L',nb)[0])c'est "mieux" comparé à trt_bin_x: 0.053163 s.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 z= 65793 trt_bin_6: 0.029141 s. z= 65793 trt_bin_61: 0.029359 s.
- W
Bonjour et merci pour les réponses.
Résultat des tests:
- 1er: trt_bin_61 de wiztricks 0.0939
return str(unpack('>L',nb)[0])
- 2ème: treat_bin d'eyquem 0.1719
return 16777216*ord(nb[0]) + 65536*ord(nb[1]) + 256*ord(nb[2]) + ord(nb[3])
- 3ème: trt_bin n°2 de josmiley 0.2650
return str((ord(b[0])<<24)+(ord(b[1])<<16)+(ord(b[2])<<8)+ord(b[3]))
- bon dernier, mon trt_bin 0.3120
c'est normal, j'avais un for
Le n°2 et le n°3 sont facilement compréhensibles.
Le n°1 est plus concis, mais on est obligé de faire confiance au unpack.
si wiztricks peut nous en dire un peu plus, ça aidera notre réflexion.
@eyquem
j'ai lu et testé des parties du #26.
j'en ai repris certaines.
@wiztricks
int('0x00010101', 16), mais ça ne correspond pas à mes données.
Salut wiztricks,
Encore un truc intéressant que tu mets sur le tapis.
Je ne connais pas le module struct. J’ai jeté un coup d’œil mais je ne comprends pas le signe ’>’:
Une petite explication ?The ‘Standard size’ column refers to the size of the packed value in bytes when using standard size; that is, when the format string starts with one of '<', '>', '!' or '='.
http://docs.python.org/library/struc...mat-characters
J’ai aussi fait des tas de tests avec diverses possibilités. Ce que j’ai de plus rapide est
Passer un objet (en fait l'adresse d'un objet), nécessaire au calcul dans une fonction, en tant qu’argument par défaut donne une vitesse plus élevée dans une exécution répétée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 def treat_binF(nb,lord = ord): return lord(nb[0])*16777216 + lord(nb[1])*65536 + lord(nb[2])*256 + lord(nb[3])
J’essaye de comprendre l’utilisation des fonctions du module struct pour inclure ce calcul dans ma série de tests. Mais il semble bien que ça va être le plus rapide de tout.
Salut eyquem,
il s'agit des conventions little et big endian. Un petit lien vaut mieux qu'un long discours sur l'endianness.
Endianness
merci kango
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager