2008-11-05 15 views
1

J'essaie d'extraire plus de performance de mon pipeline de rendu. La partie (de loin) la plus lente effectue un java.awt.imaging.LookupOp sur une grande image.Recherche Op performance

La taille de l'image est d'environ 2048x2048.

J'ai compris que faire le filtre avec l'opération de dessin est beaucoup plus rapide que d'appeler la méthode de filtrage. Cependant, cela nous laisse toujours avec des opérations de recherche qui prennent environ 250ms (ou 4 fps). Est-ce que quelqu'un a des conseils de rendu?

Heres essentiellement ce que nous faisons:

public void paint(Graphics g) 
{ 
    if(recalcLUT) 
    { 
     Graphics2D g2d = (Graphics2D) displayImage.getGraphics(); 
     g2d.drawImage(srcImage, lut, 0, 0); 
    } 

    Graphics2D g2d = (Graphics2D) g; 
    g2d.clearRect(0, 0, this.getWidth(), this.getHeight()); 
    AffineTransform at = new AffineTransform(); 
    at.setToIdentity(); 
    at.scale(scale, scale); 
    g2d.drawImage(displayImage, at, null); 
} 

la variable LUT est un LookupOp généralement un ShortLookupOp, l'image d'une image en niveaux de gris 16bit

Merci

Ryan Bucher:

Je sais il y a d'autres optimisations de performance évidentes qui pourraient être faites ici. Mais le problème majeur est juste de faire l'opération LookupOp donc je suis à la recherche de conseils à ce sujet. Les Ops de recherche sont essentiellement l'endroit où vous créez un tableau et au lieu de rendre chaque pixel de l'image comme couleur, vous utilisez la couleur comme index dans le tableau et restituez la couleur comme valeur dans l'index. Dans cet exemple particulier, je l'utilise pour faire des opérations simples de luminosité/contraste. Vous pouvez également implémenter ceci en utilisant un reseauOp qui est essentiellement un moyen d'appliquer une fonction linéaire à la valeur de tous les pixels. Mais cela s'avère être plus lent.

Répondre

1

Je n'ai pas utilisé java depuis près de huit ans, donc une partie de la syntaxe peut ne pas être pertinente.

La clé de tout type de performance concernant une boucle est de pousser le plus de choses possible en dehors de la boucle. Si vous ne pouvez pas alors effectuer des calculs seulement quand ils changent. Il est souvent préférable d'attendre jusqu'à la dernière minute pour recalculer afin de pouvoir mettre en cache plusieurs modifications.

  1. Déplacez toute la construction d'objet en dehors de votre boucle de rendu. Si vous savez d'avance combien d'objets vous avez besoin, passez-les; Si vous n'utilisez pas un pool d'objets, faites en sorte que la fabrique crée des objets en dehors du renderloop. Cela vous sauvera le temps de construction/destruction.

  2. Calculez votre AffineTransform uniquement lorsque l'échelle change. Poussez-le en dehors de la boucle de peinture et transmettez-le (comme une référence constante ... existent-ils en Java? Je suis en C++ depuis trop longtemps)

  3. Vous n'avez pas besoin d'appeler at.setToIdentity () comme votre AffineTransform doit par défaut à la matrice d'identité (cochez cette case)

  4. Est-ce que recalcLUT doit être appelé à chaque image? Est-il logique de définir recalcLUT sur false après avoir exécuté l'instruction if?

Je ne suis pas sûr de l'objectif du LookupOp. Si vous me donnez un peu plus d'informations sur ce qu'il fait, je pourrais peut-être suggérer plus.

Espérons que cela aide.

0

Avez-vous la possibilité de pousser ce traitement sur le GPU? Plusieurs pipelines matériels accéléreront considérablement le traitement.

Si vous ne pouvez pas alors, vous devriez envisager de paralléliser le LookupOp sur la CPU. D'après ce que je comprends de chaque recherche peut être fait isolément. Par conséquent, vous pouvez générer plusieurs threads (le nombre dépend de votre CPU Arch et de tout ce qui se passe en même temps) et demander à chaque thread de rechercher une partie de l'image. Vous aurez besoin d'un sémaphore lors de chaque exécution de la mise à jour pour attendre que tous les threads se terminent. Dans les deux cas, vous devez effectuer les opérations suivantes pour réduire la consommation de mémoire pour chaque image non modifiée. À moins que votre framerate ne soit plafonné, plus vous avez d'images, plus vous avez de chance que rien n'a changé. Cela vous évitera de faire un travail inutile.

//Has filter or source image changed? 
// yes, recalculate filter and cache 
// no, render cached image 

Enfin, avez-vous une visibilité sur l'implémentation de LookupOp? Que fait-il, y at-il des améliorations de performances qui peuvent être glanées en écrivant vous-même l'implémentation (cela devrait être un dernier recours).