Forum Liberty Basic France

Débutant » Accélérer un code trop lent plus d'un million de calcul...
Le 11/10/2015 à 14h36

Modérateur

Groupe: Modérateur

Inscrit le: 30/03/2011
Messages: 341
Bonjour à tous,

Pour un projet personnel je voulais créer un générateur d'image pure (image aléatoire qui n'existent pas).
J'ai donc créé le code ci dessous.

Le problème qui se pose, c'est la lenteur de LB (4.5 en plus ! ^^)

Je lui demande de faire près 1.4 millions de calculs ce qui je peux reconnaître est lourd mais avec mon matériel cela ne devrait pas poser de soucis (i7 4 coeurs 3ghz + 16 Go ram 1600Mhz + nvidia 840M 2Go dédié + SSD EVO 250 Go).... Pourtant ca ram, quand je dit que ca ram ca ram ^^ !!! vous pourrez le constater vous même. Pour faire la page en entier il faut compter 5 bonnes minutes !!! (je vous ai mis que 5 lignes au lieu de 500 pour vous montrer que même comme cela ca met du temps).

Je sais que mon code est optimisable je l'ai dailleur beaucoup améliorer et sa rapidité augmenter à chaque version mais certains ne connaîtrait pas un moyen radical d'accélérer le processus ? Que cela génère l'image entière en quelques secondes ?

Merci :)




Code VB :
'itarius projet - 2013/2015    -
'alexandre lomuto              -
'last upgrade : 10/11/15       -
'-------------------------------
'v1.01.01.00

[ini]
'fenetre principale--------------------------------------------------------------------------
nomainwin
WindowWidth = DisplayWidth
WindowHeight = DisplayHeight
Global ncx, ncy, lc
lc = 1
ncx = 1340   'nbre de case en x
ncy = 5'00  'nbre de case en y

optionG = 1 : spectreValor = 2
 
dim cas(ncx,ncy)
 
graphicbox #itarius.map, 10, 10, DisplayWidth-20, DisplayHeight-250
button #itarius.stop, "Calculer", [mesure],UL 20,545,120,25
'button #itarius.save, "Arrêter", [nf],UL int(WindowWidth/1.12),int(WindowHeight/6),120,25
button #itarius.load, "Sauvegarder", [save],UL 145,545,120,25
button #itarius.color, "Charger", [load],UL 270,545,120,25
button #itarius.time, "Spectre", [spectre],UL 395,545,120,25
button #itarius.time, "A Propos", [about],UL int(WindowWidth-150),545,120,25
textbox #itarius.data, int(WindowWidth/80), int(WindowHeight/1.32), int(DisplayWidth-40), 150
 
open "itarius projet - 1.01" for window_nf as #itarius
#itarius, "trapclose [quit]"
#itarius.map "down; setfocus"
#itarius.map "flush"
wait
 
'itarius algorythme ------------------------------------------------------------------------
[mesure]
gridx$ = " "
#itarius.data, gridx$
valX = 2
valY = 2
cas(ncx,ncy) = 0
#itarius.map, "font times_new_roman 1"
for y = 1 to ncy+1
    for x = 1 to ncx
       valor = int(rnd(1)*255+1)
       select case spectreValor
        case 0 , 1
            r = valor
            v = r : b = r
        case 2
            r = int(rnd(1)*255+1)
            v = int(rnd(1)*255+1)
            b = int(rnd(1)*255+1)
            valorTOTAL$ = str$(r) + "|" + str$(v) + "|" + str$(b)
            gridx$ = gridx$ + " " + valorTOTAL$
       end select
       #itarius.map "color ";r;" ";v;" ";b;";"
       #itarius.map "set ";valX;" ";valY
       #itarius.map "flush"
       '#itarius.map "backcolor ";r;" ";v;" ";b;";"
       '#itarius.map "place ";valX;" ";valY;";|";cas(ncx,ncy)
       valX = valX + lc '-0.05
    next
    valX = 2
    valY = valY + lc
next
#itarius.data, gridx$
wait
 
[about]
notice " " + chr$(13) + "Itarius ® 2013-2015 Par Unlimited Corporation"
wait
 
'quitter------------------------------------------------------------------------------------
[quit]
if spectre = 1 then
    close #spectre
    spectre = 0
    wait
end if
 
close #itarius
end
 
[save]
open "data.bat" for output as #grid
print #grid, ":start"
print #grid, "echo "; gridx$
print #grid, "goto start"
close #grid
notice "Données sauvegardés"
wait
 
[nf]
wait
 
[load]
run "data.bat"
wait
 
[resolution]
close #itarius
optionG = 2
if change = 1 then optionG = 1
goto [ini]
 
 
[spectre]
if spectre = 1 then close #spectre
spectre = 1
 
WindowWidth=300 : WindowHeight=200
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
button #spectre.stop, "Fermer", [quit],UL 40,150,220,25
button #spectre.1, "255 - Niveaux de gris", [G],UL 40,50,220,25
button #spectre.2, "255+3 - Couleurs", [C],UL 40,80,220,25
open "spectre" for window_popup as #spectre
wait
 
[G]
notice "changement effectué !"
spectreValor = 1
wait
[C]
notice "changement effectué !"
spectreValor = 2
wait
 




Edité par atomose Le 11/10/2015 à 14h37
____________________
Yo !

MSN Web    
Le 11/10/2015 à 17h39

Administrateur

Groupe: Administrateur

Inscrit le: 04/03/2012
Messages: 2083
J'ai un peu simplifié ton code, je pense que c'est le temps minimum pour afficher point par point
Il est tellement content, qu'on ne peut plus l'arrêter. Faut attendre qu'il ait fini.
Code VB :
 
 
nomainwin
WindowWidth = 700
WindowHeight = 500
BUTTON  #itarius.end, "stop", [stop], UL, 20, 30, 30, 20
graphicbox #itarius.map, 5, 5, 660, 470
open "test" for window_nf as #itarius
#itarius, "trapclose [quit]"
#itarius.map "down; setfocus"
#itarius.map "flush"
for y = 1 to 100
    if sto=1 then exit for
    for x = 1 to 200
       if sto=1 then exit for
       #itarius.map "color blue"'
       #itarius.map "set ";x;" ";y
       #itarius.map "flush"
       if sto=1 then exit for
    next
    if sto=1 then exit for
next
wait
[stop]
  sto=1
  wait
[quit]
  sto=1
close #itarius
end
 
 
____________________
Roro

   
Le 12/10/2015 à 00h10

Modérateur

Groupe: Modérateur

Inscrit le: 30/03/2011
Messages: 341
C'est très simplifié merci ^^

Mais n'est-il pas possible de tous les afficher ensemble ? J'ai remarquer que avec le flush, si on met la fenêtre dans la barre des taches pendant que cela génère les points, puis que l'on ré-agrandi la fenêtre quelques seconde plus tard les points s'affichent très très rapidement !

Mr flush pourrait il arranger cela ?
____________________
Yo !

MSN Web    
Le 12/10/2015 à 09h44

Administrateur

Groupe: Administrateur

Inscrit le: 04/03/2012
Messages: 2083
Le flush donne une adresse au processeur qui va chercher en RAM le paquet d'octets de l'image entière.

Quand tu génère et affiche point par point, JB envoie les ordres un par un au processeur

Il manque à JB et à LB les instructions "Peek" et "Poke" des anciens Basics, qui permettaient de travailler directement en mémoire. (en manipulant des adresses et des octects). Vulgairement appelé: "Langage machine"
Il y a certainement une DLL qui doit faire ça
____________________
Roro

   
Le 29/11/2015 à 09h49

Libertynaute Débutant

Groupe: Membre

Inscrit le: 03/05/2012
Messages: 17
Coucou tout le monde.
Je ne viens pas souvent ici, mais un petit peu quand même.
(À noter que je ne programme pas en LibertyBasic, alors tout ce que je dis peut être inexact).

Il ne faut pas faire de flush à chaque tour de boucle, ça ralentit tout et ça mange plein de mémoire. Il faut faire le flush uniquement à la fin de la boucle principale. Ton image apparaîtra d'un seul coup. Elle mettra peut-être un peu de temps à apparaître, mais le temps d'attente total sera beaucoup plus court que de réafficher à chaque pixel.

J'ai lu quelque morceaux de documentation de LibertyBasic (désolé, c'est en anglais).
http://lbpe.wikispaces.com/SegmentsAndFlushing
http://basic.wikispaces.com/FlushConserveBMP
http://www.libertybasicuniversity.com/lb4help/0D14N5.htm

Apparemment, une Graphicbox, c'est pas simplement un carré plein de pixels qu'on colorie. C'est un objet qui permet de stocker des intructions de dessins, de les regrouper en "segment", de réafficher un segment, etc.

L'instruction "flush" effectue deux choses différentes : rendre l'image persistante (sinon elle disparaît quand on minimise la fenêtre) et stocker les instructions de dessins en cours dans un segment. Je trouve ça bizarre qu'une instruction fasse deux choses, mais c'est pas grave, on va faire avec.

Si tu fais plein de flush, la machine doit stocker plein de segments, ça prend plein de mémoire, c'est lent et ça ne sert à rien. Un seul flush tout à la fin de la génération de l'image, ça suffit.

Pour plus tard, si tu veux faire une application génèrant plusieurs images aléatoires (par exemple, une nouvelle image à chaque fois que tu appuies sur un bouton), il faudra faire attention de supprimer les segments précédents. Sinon tu vas à nouveau remplir la mémoire pour rien. L'instruction pour tout vider (l'image en cours et les segments précédents), c'est

Code VB :
#itarius.map "Cls"


Ou sinon, tu dois pouvoir faire des trucs plus subtils : supprimer le segment précédent avec DelSegment et dessiner une nouvelle image par dessus l'autre. Ou bien bidouiller quelque chose avec des Discard et des Redraw. Ou même préparer ton image en mémoire, et l'afficher en une seule instruction avec un DrawBmp. Mais là je ne m'y connais pas assez pour t'expliquer en détail comment faire.


Autre remarque : au début de la boucle, tu génère un nombre aléatoire (la variable "valor") qui n'est utilisée que si spectreValor vaut 0 ou 1. Il vaut mieux mettre cette génération directement dans le "case 0 , 1". Ça ne changera rien de significatif pour la rapidité d'exécution du code, mais ce sera plus clair.

Et je ne suis pas sûr que le "+1" dans la génération de nombre aléatoire soit nécessaire. L'instruction "color" demande trois valeurs entre 0 et 255. Si tu mets +1, ça génère des valeurs entre 1 et 256.

Pour conclure, ta boucle de génération de l'image, je la verrais comme ça :

Code VB :
 
for y = 1 to ncy+1
    for x = 1 to ncx
       select case spectreValor
        case 0 , 1
            valor = int(rnd(1)*255)
            r = valor : v = valor : b = valor
        case 2
            r = int(rnd(1)*255)
            v = int(rnd(1)*255)
            b = int(rnd(1)*255)
            valorTOTAL$ = str$(r) + "|" + str$(v) + "|" + str$(b)
            gridx$ = gridx$ + " " + valorTOTAL$
       end select
       #itarius.map "color ";r;" ";v;" ";b;";"
       #itarius.map "set ";valX;" ";valY
       '#itarius.map "backcolor ";r;" ";v;" ";b;";"
       '#itarius.map "place ";valX;" ";valY;";|";cas(ncx,ncy)
       valX = valX + lc '-0.05
    next
    valX = 2
    valY = valY + lc
next
' Il est ici le flush, à la fin !!
#itarius.map "flush"
 
____________________
Quand l'imbécile regarde la Lune, le sage lui met un doigt.
http://recher.wordpress.com

Web    
Le 29/11/2015 à 13h10

Administrateur

Groupe: Administrateur

Inscrit le: 04/03/2012
Messages: 2083
Citation:
mais ce sera plus clair.

Si tu parle le clarté à atomose, tu va te faire insulter. :lol
____________________
Roro

   
Débutant » Accélérer un code trop lent plus d'un million de calcul...  

 |  |

1 Utilisateur en ligne : 0 Administrateur, 0 Modérateur, 0 Membre et 1 Visiteur
Utilisateur en ligne : Aucun membre connecté
Répondre
Vous n'êtes pas autorisé à écrire dans cette catégorie