Trouver valeur max [Résolu/Fermé]

boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 26 sept. 2007 à 17:21 - Dernière réponse : boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention
- 4 oct. 2007 à 16:40
Je cherche une façon ultra rapide de trouver la valeur maximale d'une grande liste de nombres. Il n'est donc pas question ici de commencer à comparer des nombres dans une boucle...

Une solution pourrait être une API (que je ne connais pas) qui s'appliquerait sur un bloc de mémoire en spécifiant un pointeur et une dimention.

Une autre solution pourrait être une fonction (que je ne connais pas) qui s'appliquerait sur un tableau. Je sais déjà comment remplir ce tableau très rapidement en copiant un bloc de mémoire directement dans ce tableau.

Merci de m'aider
Afficher la suite 

34 réponses

boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 4 oct. 2007 à 16:40
+3
Utile
Dorénavant, je vais faire comme les quelques 973,749 membres de ce forum. Les rares fois que je vais y venir ce sera uniquement pour y piquer des idées et des sources.

Plus question donc d'y poser des question, ni de répondre à des question et encore moins d'y déposer des sources. J'ai d'ailleurs enlevé les miennes hier.

Je vais faire de même avec le petit frère cpp qui de toute façon m'apparaît être un amalgame de nombreux languages dont C++...donc moins intéressant. Je crois bien que pour le C++ les sites américains sont de loin ce qu'il y a de mieux...sans vouloir offenser personne.

Je constate qu'un autre message a été déposé après le tiens et je constate aussi qu'il va dans le sens de l'idée que je me suis faite de son auteur.

Adios amigo
Cette réponse vous a-t-elle aidé ?  
Commenter la réponse de boursicotteur
FMatrix07 233 Messages postés mercredi 26 février 2003Date d'inscription 21 février 2009 Dernière intervention - 26 sept. 2007 à 17:53
0
Utile
Bonjour,
Je pense que le plus rapide est belle et bien une boucle.

@+: SCCréat
Pensez:  Réponse acceptée

Mail:
Stéphan.COCHET
Commenter la réponse de FMatrix07
cs_etniqs 201 Messages postés mardi 7 octobre 2003Date d'inscription 10 mai 2016 Dernière intervention - 26 sept. 2007 à 18:03
0
Utile
c'est quoi un bloc de mémoire ? des pointeurs ??

de toute façon, tu n'as pas le choix que de comparer des valeurs entre elles, puisque tu veux le max des valeurs, donc une boucle ... par contre, c'est elle qu'il faudra optimiser, la base est simple :

while
if tab(n) > tab(n+1) then mavaleur = tab(n)
wend
Commenter la réponse de cs_etniqs
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 26 sept. 2007 à 19:04
0
Utile
Pas le choix de comparer des valeurs... Donc, faut une boucle?

Dans Excel il y a une fonction qui compare des valeurs...sans faire de boucle...    

Max(liste de nombres ou plage d'adr contenant des nombres)

C'est quoi un bloc de mémoire, un pointeur?
Si tu sais ce qu'est une API alors examine celle-ci:

Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

· Destination
Points to the starting address of the copied block’s destination.


· Source
Points to the starting address of the block of memory to copy.


· Length
Specifies the size, in bytes, of the block of memory to copy.
Commenter la réponse de boursicotteur
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 26 sept. 2007 à 21:05
0
Utile
Une API ça s'écrit, encore faut-il avoir qlq détail.
Quel type tes nombres, intt16, int32, single, double ?

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
Kristof_Koder 920 Messages postés vendredi 3 août 2007Date d'inscription 27 octobre 2008 Dernière intervention - 26 sept. 2007 à 21:59
0
Utile
"Dans Excel il y a une fonction qui compare des valeurs...sans faire de boucle..." < Ah !! Bon ! Parce que tu connais le code exécuter par la fonction Max d'Excel toi ? Tu croit vraiment qu'il n'y a pas de boucle dans le Max() !!
Moi, je pense qu'il y en a une.
Quel que soit ce ue tu utiliseras pour faire ca, tu auras une boucle. La seule différence, c'est que si tu fais ta boucle en C ou mieux en ASM, ca va booster bien plus qu'une boucle en VB6 !!
Tu parles de bloc mémoire, de pointeur et de dimension. Pour ballader ton ptr du début à la fin du bloc, il te faudra bien une boucle ! Ou alors tu es magicien !
Commenter la réponse de Kristof_Koder
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 26 sept. 2007 à 22:36
0
Utile
Salut BruNews

Mes nombres proviennent de fichiers wave de 8 bits et 16 bits et il est inutile de préciser qu'il y en a plusieurs millions dans chaque fichier alors les boucles en VB c'est pas ce qu'il y a de mieux.

Présentement, j'utilise l'API  ReadFile pour placer ces nombres directement dans un tableau dimentionné soit en Bytes ou en Integer. C'est ultra rapide! Il faut à peine quelques mSec!

Mais çà se gâte quand je travaille avec ce tableau pour extraire les valeurs crêtes de blocs de 128 échantillons en faisant une boucle en VB. Il me faut 12 sec pour traiter un fichier de 6 millions d'échantillons alors qu'un logiciel du commerce le fait en 3 ou 4 sec. Voilà pour la lenteur de VB!

Tu dis être capable d'en écrire une?
Je sais que les API sont livrées dans des DLL et qu'il est possible d'écrire des DLL mais pour qu'elles soient rapide il ne faut pas le faire en VB. D'après ce que j'en sais, C++ est beaucoup mieux.

J'espère que cela répond à ta question.
Merci
Commenter la réponse de boursicotteur
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 26 sept. 2007 à 22:49
0
Utile
Declare Sub bnGetInt16MinMax Lib "vbMinMax.dll" (ByRef ptab As Integer, ByVal nelems As Long, ByRef pMin As Integer, ByRef pMax As Integer)
les 2 bornes min et max retournées dans pMin et pMax, OK ?

exemple:
Declare Sub bnGetInt16MinMax Lib "vbMinMax.dll" (ByRef ptab As Integer, ByVal nelems As Long, ByRef pMin As Integer, ByRef pMax As Integer)


Dim T(100) As Integer
Dim a, b
' remplir T de 100 valeurs int16
bnGetInt16MinMax(T(0), 100, a, b)
debug.Print a
debug.Print b

et la meme en 8 bits: bnGetInt8MinMax

les valeurs sont à considérer en unsigned ?

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 26 sept. 2007 à 23:38
0
Utile
Exemple fait sur Excel, je n'ai pas VB.


Option Explicit


' RECHERCHE BORMES MIN ET MAX SUR ENTIERS 16 BITS
Declare Sub bnGetInt16MinMax Lib "D:\vbMinMax.dll" (ByRef ptab As Integer, ByVal nelems As Long, ByRef pMin As Integer, ByRef pMax As Integer)
Declare Sub bnGetWordMinMax Lib "D:\vbMinMax.dll" (ByRef ptab As Integer, ByVal nelems As Long, ByRef pMin As Integer, ByRef pMax As Integer)


Sub DireInt16MinMax()
  Dim cel As Range
  Dim n As Integer, a, z
  Dim T(100) As Integer
  Set cel = Range("A1")
  n = 100
  Do
    T(n) = CInt(cel.Value)
    Set cel = cel.Offset(1, 0)
    n = n - 1
  Loop While n >= 0
 
  bnGetInt16MinMax T(0), 100, a, z
  ' SI TRAVAIL EN UNSIGNED UTILISER bnGetWordMinMax AVEC MEMES PARAMS
 
  Debug.Print a
  Debug.Print z
End Sub


DLL (2,5 Ko) ici: http://brunews.com/vbMinMax.zip

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 27 sept. 2007 à 04:03
0
Utile
Merci pour ton travail BruNews!
Malheureusement je ne réussi pas à faire fonctionner cette DLL.
Voici ce que j'ai fait:

1-J'ai d'abord déclaré les 2 fonctions dans un module:
Public Declare Sub bnGetInt16MinMax Lib "vbMinMax.dll" ( _
        ByRef ptab As Integer, _
        ByVal nelems As Long, _
        ByRef pMin As Integer, _
        ByRef pMax As Integer)


Public Declare Sub bnGetInt8MinMax Lib "vbMinMax.dll" ( _
        ByRef ptab As Integer, _
        ByVal nelems As Long, _
        ByRef pMin As Integer, _
        ByRef pMax As Integer)

2-J'ai ensuite écrit un code test dans un formulaire:
Public Sub btnTEST_Click()
    Dim T(100) As Integer
    Dim a, b, rt
    ' remplir T de 100 valeurs int16
    For rt = 0 To 99
        T(rt) = rt + 5
    Next


    rt = bnGetInt16MinMax(T(0), 100, a, b)
    Debug.Print a
    Debug.Print b
Exit Sub

=> J'ai obtenu le message suivant:
Erreur de compilation:
Function ou variable attendue

Alors je me suis dit qu'il fallait enrégistrer cette dll; ce que j'ai fait en utilisant la ligne de commande suivante: 
regsvr32 C:\windows\system\vbMinMax.dll

=> J'ai obtenu le message suivant:
C:\windows\system\vbMinMax.dll was loaded, but the DllRegisterServer entry point was not found.

DllRegisterServer may not be exported, or a corrupt version of C:\windows\system\vbMinMax.dll may be in memory. Consider using Pview to detect and remove it.

J'ai donc utilisé mon Pview pour voir tous les process actifs et il n'y avait pas trace de vbMinMax.dll.
Peut-être que le fichier n'est pas correct ou qu'il est corrompu...
...Il a pourtant fonctionné avec ton Excell!

Je vais le retélécharger et le réessayer...au cas où il aurait été corrompu lors du téléchargement (mais j'en doute).

Ce serait bien si d'autres personnes pouvaient l'essayer avec un code VB et poster ici leur résultat.

Tes 2 fonctions semblent répondre à mes besoins mais il va y avoir un autre petit problème que voici:

Les fichiers wave ont 1 ou 2 canaux et les données sont ordonnées en conséquence. Le tableau qui recevra ces données doit être dimentionné en conséquence.
 
Ceci veut dire que pour un fichier wave à 1 canal, le tableau doit avoir 1 seule dimention (0  à  N-1 échantillons).
Pour un fichier wave à 2 canaux, ce sera 2 dimentions (0 à 1, 0 à N-1).

Il faudrait avoir la possibilité d'extraire les valeurs Min Max pour chacun des 2 canaux (si il y en a 2).
Il suffirait donc d'ajouter une autre variable à tes fonctions...

Encore une fois merci pour ton aide.
Commenter la réponse de boursicotteur
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 27 sept. 2007 à 08:29
0
Utile
bnGetInt16MinMax T(0), 100, a, b
C'est "Sub" donc pas "rt = bnGetInt16MinMax..."
Mais c'est pas idiot comme truc, je peux modifier pour retourner le Min, ça gagnerait qlqs cycles.
Teste déjà comme ça.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 27 sept. 2007 à 16:29
0
Utile
Voila, çà fonctionne mais... pas complètement!

1-Ce matin j'ai réalisé que la déclaration contenait un Sub et non un Function comme c'est généralement le cas pour les API.
 Alors, dans la ligne d'appel de mon code Test, j'ai changé le rt = machintruc par Call machintruc et çà a fonctionné...pour bnGetInt16MinMax seulement.

bnGetInt8MinMax m'a retourné le message suivant:

Erreur d'exécution 453
Point d'entrée bnGetInt8MinMax d'une DLL introuvable dans vbMinMax.dll.

Ceci veut dire que le nom bnGetInt8MinMax n'a pas été trouvé dans la DLL. Il y a probablement erreur sur le nom...

2-Tu dis pouvoir changer la façon d'appeler ta sub et gagner quelques cycles. Tu parles sans doute de la convertir en fonction et de l'appeler comme une fonction en écrivant rt= machintruc.

Ceci aurait l'avantage de standardiser la déclaration et ta DLL serait plus facilement utilisable par tout le monde.

Par contre, il est probable que tes fonctions ne pourraient pas retourner 2 valeurs Min et Max.   Moi, j'ai besoin des deux!

Peut-être alors que tu pourrais changer ça pour 2 fonctions distinctes Min et Max qui seraient bien optimisées et qui pourraient utiliser un tableau dimentionné en Byte et Integer.

NOTES:
a) Pour pouvoir lire correctement les valeurs d'un fichier wave 8 bits avec l'API  ReadFile, le tableau doit absolument être dimentionné en Byte. Pour un fichier 16 bits, il doit être en Integer.

b) Pour que la fonction puisse fonctionner autant en Byte qu'en Integer, il suffit simplement (parfois) de changer l'argument ByRef dans la déclaration. Je ne sais pas ce qui se passe en réalité mais çà fonctionne parfois.

3-En essayant d'intégrer ta sub dans mon prog pour voir le temps d'exécution, j'ai réalisé que je t'avais induit en erreur sur la dimention du tableau à lire pour un fichier wave à 1 canal.

Je croyais que c'était T(n) mais en réalité j'ai utilisé T(0, n) car c'est plus flexible pour ma sub. Pour un fichier wave à 2 canaux, je n'ai qu'à utiliser T(1, n) et je suis en affaire.

J'aurais facilement pu modifier ma sub (temporairement) pour voir ce que serait le temps d'exécution mais je ne l'ai pas fait.

4-Enfin, il me faut pouvoir trouver les valeurs Min et Max des 2 canaux quand il y en a 2 sur le fichier wave. Donc, il faudrait ajouter une autre variable dans tes fonctions pour choisir sur quelle canal (0 ou 1) de la première dimention on travaille.

5-QUESTION
Si une DLL est écrite en VB, est-ce que la fonction qu'elle contient est exécutée
    "plus rapidement",
    "plus lentement"
    ou "à la même vitesse" 
que si cette même fonction était écrite à l'intérieur des lignes de code du prog?

Bon! Je crois que je n'ai rien oublié...

En tous cas j'ai bien hâte de voir le temps d'exécution et je crois que je ne vais pas résister à l'envie de satisfaire ma curiosité en modifiant ma sub temporairement.

En tous cas tu peux être certain que je vais t'informer des résultats quand je les aurai.
Commenter la réponse de boursicotteur
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 27 sept. 2007 à 17:24
0
Utile
Bon!
J'ai satisfait ma curiosité et voici le résultat de mes tests:

J'ai utilisé un fichier wave 1 canal 16 bits contenant 5,590,602 échantillons. Pour le moment, ta dll ne peut pas extraire les valeurs d'un 2è canal et je ne peux pas accéder à ta fonction 8 bits.

VOICI LE TRAVAIL FAIT PAR MA SUB
 J'ai fragmenté le fichier wave en blocs de 256 échantillons.

J'ai trouvé les valeurs min et max de chacun de ces blocs et calculé leur valeur absolue. J'ai conservé la plus grande des deux et je l'ai convertie en 8 bits unsigned.

Avec ces 21839 valeurs obtenues, j'ai fabriqué un petit fichier crête.

RÉSULTAT DE MES TESTS
Sans ta dll:     7715, 8068, 7074, 7035 mSec
Avec ta dll:    3363, 3305, 3405, 3322 msec

En gros, ta dll a coupé en deux le temps d'exécution de ma sub qui fait plus qu'extraire des valeurs mais c'est tout de même cette extraction qui consommait le plus de temps.

Alors MERCI, MERCI et MERCI

PS:
Les nombres 16 bits sont signed (-32768 à 32767)
Les nombres 8 bits sont unsigned (0 à 255)
Commenter la réponse de boursicotteur
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 27 sept. 2007 à 19:07
0
Utile
Autres résultats de test:

J'ai refait une autre série de test en regardant cette fois le temps total de ma sub versus le temps total consacré à l'extraction uniquement. J'ai utilisé le même fichier mais cette fois mon vieux ordi en manque de mémoire était un peu plus lent.

                  Total          Extraction
sans dll       7675          4675
                  7687          4733
                  7690          4465
                  7645          4664
      Moy=  7674.25     4634.25    => 60.38%
      Total - Extraction = 3040

avec dll       3917          695
                   3954          636
                   3901          691
                   3880          683
      Moy=   3913          676.25    => 17.28%
      Total - Extraction = 3236.75

J'ai fait un test après avoir remplacé les arguments INTEGER de la déclaration par BYTE et dimentionné T() en BYTE

Ta dll n'a pas planté mais pour des valeurs variant de 0 à 255 elle m'a retourné Min=128 et Max = 126

DERNIER POINT
Si tu décides d'aller avec 2 fonctions distinctes Min et Max, je vais devoir appeler les deux fonctions dans ma sub et leurs temps d'exécution va d'additionner.

Ce sera donc avantageux pour moi SI la somme de ces 2 temps d'exécution est comparable à celui de MinMax actuel (676 mSec).
Commenter la réponse de boursicotteur
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 27 sept. 2007 à 19:25
0
Utile
Dans une dll ou non, c'est toujours du vb alors rien à gagner, plus surement à y perdre vu l'appel COM.
La version n'est pas implémentée dans la dll, normal qu'il ne la trouve pas.
Tu veux la bit non signé ?
Si tu veux on peut aussi essayer d'abaisser les temps, je teste plusieurs algos et tu testes en mesure.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 27 sept. 2007 à 19:28
0
Utile
oups le 8 de mon clavier déconne, donc je disais la 8 bits n'y est pas encore.
Je la fais.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 27 sept. 2007 à 20:00
0
Utile
ATTENTION, DLL SUR SERVEUR EST CHANGEE !!!

Va la recharger et modifie les déclarations comme exemple dessous, now ce sont des func qui retournet le maxi. Fais du copier coller pour éviter erreurs.

Declare Function bnGetInt16MinMax Lib "vbMinMax.dll" (ByRef ptab As Integer, ByVal nelems As Long, ByRef pMin As Integer) As Integer
Declare Function bnGetWordMinMax Lib "vbMinMax.dll" (ByRef ptab As Integer, ByVal nelems As Long, ByRef pMin As Integer) As Integer
Declare Function bnGetByteMinMax Lib "vbMinMax.dll" (ByRef ptab As Byte, ByVal nelems As Long, ByRef pMin As Byte) As Byte


Sub DireInt16MinMax()
  Dim cel As Range
  Dim n As Long
  Dim a As Integer, z As Integer
  Dim T(100) As Integer
  Set cel = Range("A1")
  n = 100
  Do
    T(n) = CInt(cel.Value)
    Set cel = cel.Offset(1, 0)
    n = n - 1
  Loop While n >= 0
  z = bnGetInt16MinMax(T(0), 100, a)
  Debug.Print a
  Debug.Print z
End Sub


Sub DireByteMinMax()
  Dim cel As Range
  Dim n As Long
  Dim a As Byte, z As Byte
  Dim T(100) As Byte
  Set cel = Range("A1")
  n = 100
  Do
    T(n) = CByte(cel.Value)
    Set cel = cel.Offset(1, 0)
    n = n - 1
  Loop While n >= 0
  z = bnGetByteMinMax(T(0), 100, a)
  Debug.Print a
  Debug.Print z
End Sub

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 28 sept. 2007 à 00:06
0
Utile
Résultat de mes tests avec la nouvelle dll:

POUR LA 16 BITS
Les conditions sont identiques au test précédent
Tantôt j'avais des moyennes de 
  3913 pour ma sub et 672 pour l'extraction

Maintenant j'ai des moyennes de 
  3188 pour ma sub et 683 pour l'extraction

Mon ordi s'est réveillé et ta dll est aussi rapide!

POUR LA 8 BITS
Elle est maintenant accessible mais pour les valeurs retournées c'est pas encore ça.
Je lui ai fait bouffer un tableau de 25 valeurs (5 à 29) et elle m'a retourné Min0 et Max désastre
En effet Max retourne des valeurs différentes à chaque démarrage de l'application et ce, avec toujours les mêmes valeurs dans le tableau.

SUGGESTION
Les performances de ta dll ont dirigé mon attention sur le reste de ma sub et j'ai trouvé des façons de gagner des SECONDES.

Pour cela, il faudrait ajouter une autre variable à ta fonction et cela aurait l'autre avantage de rendre ta fonction encore plus flexible.

Voici ce que serait ta fonction 16 bits:

bnGetInt16MinMax (ByRef pTab As Integer, 
                                By? pDimA As comme tu veux
                                By? pDimB As long
                                ByVal nElems As Long, 
                                ByRef pMin As Integer) As Integer

pTab pointe sur un tableau à 2 dimentions T(A, B)
        où "A" est pour référencer les canaux 
             "B" est pour référencer les échantillons
pDimA pointe sur le canal (0 ou 1) dont on veux
        extraire Min et Max
pDimB pointe sur l'échantillon où débute le bloc à examiner
            (actuellement elle débute toujours à 0)
nElems est la grosseur du bloc à examiner
 
Même principe pour ta fonction 8 bits.

Evedemment, ce serait encore plus rapide pour ma sub si ta fonction pouvait accéder aux données directement dans la mémoire à l'aide d'un handle que je crée par l'api CreateFile car je n'aurais alors plus besoin de charger un tableau que je détruit aussitôt mon fichier crête fabriqué.

Ceci aurait le double avantage de gagner des mSec et surtout d'épargner la mémoire RAM.

Cependant, cela aurait pour effet de rendre tes fonctions moins utilisables par monsieur tout le monde et en plus, c'est probablement beaucoup plus "risqué" côté programmation.
Commenter la réponse de boursicotteur
BruNews 21054 Messages postés jeudi 23 janvier 2003Date d'inscription 7 novembre 2014 Dernière intervention - 28 sept. 2007 à 10:30
0
Utile
Exact pour la 8 bits, j'ai remis la DLL, teste.
J'ai aussi fait qlqs modif algo de bnGetInt16MinMax, tu me diras si les temps sont mieux.

Si test tableau et le handle fichier ne te servent plus à rien après avoir trouvé le mini maxi alors dis moi les détails et on fera tout dans la DLL qui te retournera mini maxi, cette fois oui que ça va booster.

ciao...
BruNews, MVP VC++
Commenter la réponse de BruNews
boursicotteur 201 Messages postés mercredi 25 septembre 2002Date d'inscription 10 novembre 2007 Dernière intervention - 28 sept. 2007 à 23:24
0
Utile
Désolé pour ma lenteur à répondre...
Mon fournisseur internet était down...




### INTERPRÉTATION DES TEMPS ###
Les résultats de mes tests sont "moyennement" fiable pour 2 raisons:


1-Je mesure avec l'API GetTickCount (précision 1 mSec).
  J'échantillonne l'horloge immédiatement AVANT et APRÈS ta fonction.  La différence de ces 2 valeurs est cumulée à chaque passage de boucle et cela me donne une valeur totale. Ta fonction est plus rapide que la précision de GetTickCount et je multiplie cela par un gros chiffre alors je suis surpris d'avoir des résultats pas plus variables.


2 Mon ordi manque de RAM. Chaque fois qu'il sauvegarde sur le disque dur des choses (pas requises dans l'immédiat) pour libérer du RAM requis immédiatement, cela ralentie le déroulement du prog...et par conséquent augmente mes temps de lecture.


Il faut donc les interpréter comme une tendance seulement.




### FONCTION 16 BITS ###
Elle semble aussi rapide qu'avant.
Cette fois-ci j'ai obtenu 731mSec (moy de 8 valeurs de 666 à 816)


Mais faut préciser que ce 731 (temps d'extraction) est la somme de 2 temps:
Celui de ta DLL et celui d'une ligne de code VB (que je croyais insignifiante)


J'ai testé pour voir la part de chacun:
329 mSec  pour ta DLL
402 mSec  pour ma ligne de code VB


Ce 329 mSec est le temps pris pour extraire 43677 fois (5,590,602/128) les Min et Max parmis 128 nombres.


C'est à peine 7.53 uSec par extraction!
Pour moi c'est assez optimisé... BRAVO!




### FONCTION 8 BITS ###
Cette fois-ci elle fonctionne à la perfection. BRAVO!


J'ai testé avec un fichier (1 canal 8 bits) de 6,463,972 échantillons. Ta fonction a donc traité 50,500 segments de 128 échantillons.


Le temps pris (par elle seule) est:
438 mSec (moy de 8 tests 380 à 492)


C'est 8.68 uSec par extraction
 
C'est 15% de plus que l'autre fonction mais c'est peut-être dû au format BYTE car les processeurs ne traitent pas tous les formats à la même vitesse...
J'ai entendu dire que le format le plus rapide est LONG.




### FINALISATION DES 2 FONCTIONS ###
1- A mon avis, la fonction 16 bits est suffisamment performante mais c'est toi qui décides.


2- Pour la fonction 8 bits moins rapide, faudrait voir si c'est à cause du format BYTE ou de l'algorythme et prendre une décision en conséquence. 
Moi je peux très bien vivre avec 8.68 uSec.


3- J'aimerais ajouter une dernière variable de sortie à ta fonction. Il s'agit de l'amplitude maximale Amax calculée par la ligne de code chronométrée avec ta fonction et qui bouffe plus de temps qu'elle.


   Pour la fonction 16 bits ma ligne de code est:
   Amax = IIf(Abs(xMin) < Abs(xMax), Abs(xMax), Abs(xMin))


   Pour la fonction 8bits ma ligne de code est:
   Amax = IIf(Abs(xMin - 128) < Abs(xMax - 128), Abs(xMax - 128), Abs(xMin - 128))


4- Pour rendre ces 2 fonctions aussi flexibles que possible (et utilisables par  mon prog), il reste à utiliser un tableau à 2 dimentions et à ajouter les 2 variables permettant de pointer sur le canal et sur le début du bloc.


5- Pour faciliter l'usage de tes fonctions et leur donner une apparence aussi prêt que possible des fonctions du commerce, j'aimerais te suggérer ce format ci:


Amax= bnGetInt16MinMax (
               ByRef pTab As Integer,
              By? pDimA As long
              By? pDimB As long
              ByVal nElems As Long,
              ByRef outMin As Integer
              ByRef outMax As Integer
              ) As Integer


Amax= bnGetByteMinMax(
              ByRef pTab As Byte
             By? pDimA As long
              By? pDimB As long
              ByVal nElems As Long,
              ByRef outMin As Byte
              ByRef outMax As Byte
              ) As Byte


Amax   est la valeur maximale de l'amplitude dans le bloc.
            Cette valeur étant "dédiée à ma seule application", j'ai pensé qu'il serait préférable de la transmettre de cette façon pour préserver l'aspect "général" de ta fonction qui sera utilisée par beaucoup de personnes et à bien des sauces.

pTab   pointe sur un tableau à 2 dimentions T(A, B) où
           "A" référence les canaux
           "B" référence les échantillons

pDimA  pointe sur le canal (0,1, ...) dont on veux extraire Min et Max

pDimB  pointe sur l'échantillon où débute le bloc à examiner (actuellement elle débute toujours à 0)

nElems est la grosseur du bloc à examiner

outMin est la valeur minimale trouvée dans le bloc

outMax est la valeur maximale trouvée dans le bloc




### BYPASSER LE TABLEAU ###
J'ai lancé cette idée en rêvant un peu tout haut et sans vraiment savoir de quoi je parlais car je suis ici à la frontière de mes connaissances.


Je peux me tromper (tant mieux si c'est le cas) mais après réflexion, je ne suis pas certain que cela va épargner temps et RAM. Je m'explique...


Actuellement, je dois:
1- Mettre le fichier wave en mémoire virtielle et obtenir son handle avec l'API
   hFile = CreateFile(vFilePath, GENERIC_READ, FILE_SHARE_READ, 0&, OPEN_EXISTING, 0&, 0&)


2- Pointer sur le début du data dans le fichier virtuel avec l'API
   SetFilePointer hFile, vFileOffset, 0&, FILE_BEGIN


3- Remplir le tableau avec un segment de 128 échantillons avec l'API
   ReadFile hFile, T16(0), vFileBlocs * 128, Ret, 0&


Cela me donne le tableau que ta DLL traite.




## 1ère Question ##
Est-ce que ces API seront plus rapide si c'est C++ qui appelle au lieu de VB?  
=> Moi je crois que non alors pas profitable de mettre cela dans la fonction.


## 2è Question ##
Est-ce que te donner un handle au lieu d'un tableau va épargner temps et RAM?
Oui...si tu es capable de comparer des nombres RAPIDEMENT sans devoir passer par la mémoire RAM.

À mon avis, c'est très loin d'être gagné car les obstacles sont nombreux:
1- Dans le fichier virtuel, tout est en octet alors pour avoir un INTEGER il faut aller chercher les 2 octets qui le compose et les fusionner correctement.


2- Chaque lecture du fichier virtuel prend un certain temps qui croît moins rapidement (enfin je crois) que la grosseur du bloc lu. Si j'ai raison alors il y a grand intérêt à lire par gros bloc plutôt que par petit bloc. Or, pour comparer des nombres dans la mémoire virtuelle, il faudra (sauf erreur) lire par très petits blocs.


etc


 
Commenter la réponse de boursicotteur

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

trouver valeur max - page 2