2010-05-20 3 views
1

Je recherche une classe matricielle 2D (ou bitmap) flexible mais aussi rapide. Le contenu Une classe souple devrait vous permettre de choisir les dimensions au cours de l'exécution, et ressemblerait à quelque chose comme ça (simplifié):Optimisation d'une classe matricielle/bitmap C++

class Matrix 
{ 
public: 
    Matrix(int w, int h) : 
    data(new int[x*y]), width(w) {} 

void SetElement(int x, int y, int val) 
{ 
    data[x+y*width] = val; 
} 

// ... 
private: // symbols 
    int width; 
    int* data; 
}; 

Une solution plus rapide souvent proposée en utilisant des modèles est (simplifié):

template <int W, int H> 
class TMatrix { 
    TMatrix() data(new int[W*H]) {} 

    void SetElement(int x, int y, int val) 
    { 
    data[x+y*W] = val; 
    } 

    private: 
    int* data; 
}; 

C'est plus rapide car la largeur peut être "inline" dans le code. La première solution ne le fait pas. Cependant, ce n'est plus très flexible, car vous ne pouvez plus changer la taille à l'exécution. Donc ma question est: Existe-t-il une possibilité de dire au compilateur de générer du code plus rapide (comme lors de l'utilisation du template), quand la taille du code est fixe et génère du code flexible quand son runtime dépend?

J'ai essayé d'y parvenir en écrivant "const" là où c'est possible. Je l'ai essayé avec gcc et VS2005, mais sans succès. Ce type d'optimisation serait utile pour de nombreux autres cas similaires.

+0

"Ce type d'optimisation serait utile pour de nombreux autres cas similaires." Est-ce que vous dites cela basé sur des tests réels, ou simplement sur vos croyances? Rappelez-vous, l'optimisation prématurée et tout cela. –

+0

Avez-vous profilé ce code? Pour tout ce qui n'est pas intégré, il est peu probable que la multiplication et l'addition supplémentaires apparaissent même dans perf. Sur de nombreuses plates-formes, l'utilisation de la prise en charge mathématique du vecteur matériel et/ou la copie de valeurs en masse plutôt qu'une à la fois vous permettra de gagner beaucoup plus que d'essayer de vous débarrasser de deux opérations scalaires. –

Répondre

0

Je voudrais juste aller avec la première version, moi-même. Mais, si vous voulez vraiment essayer d'obtenir le meilleur des deux mondes, vous pouvez avoir une classe Matrix qui contient un pointeur vers un type d'implémentation polymorphe. Pour les tailles courantes (disons jusqu'à 4x4), vous pouvez pointer sur les instanciations de modèles, et pour les plus grandes, vous pouvez pointer vers une implémentation qui gère le cas MxN général. Cela dit, je pense que tous les appels virtuels indirects & annuleraient toute amélioration des performances qui pourrait provenir des modèles. Je ne pense pas que vous pouvez avoir votre gâteau & le manger aussi, dans ce cas. Si vous avez toujours affaire à des données dont la taille est connue au moment de la compilation (graphismes/vecteurs de géométrie par exemple), il vaut mieux utiliser la version du modèle (stockage éventuel des données en taille statique (allocation sans tas)) tableaux). Si vous avez besoin d'une fonctionnalité générale pour des données arbitraires, utilisez plutôt la version dynamique.

0

Bien sûr, vos besoins peuvent différer, mais je passerais la génération automatique et juste aller avec un simple ensemble & des versions "fixes". Par exemple. Vector3, Vector4, Matrix3x3, Matrix3x4 et Matrix4x4. Je suppose que vous pourriez tirer tous ceux de la version sur gabarit, mais cela ne fera aucune différence de performance particulière.

Y a-t-il une raison particulière pour laquelle vous voulez pouvoir modifier les dimensions lors de l'exécution? Parce que je suggérerais que la simple copie de l'un à l'autre ne serait pas terriblement coûteuse pour les cas (ce que je soupçonne d'être rares) où le changement doit se produire. Enfin, quelque chose que j'ai vu est d'avoir un accès aux éléments nommés ainsi que le tableau, mais vous ne pouvez le faire qu'avec des types "codés en dur". Quelque chose comme:

class Vector3 
{ 
public: 
    // other stuff... 

    union 
    { 
     struct { float x, y, z; }; 
     float m[3]; 
    }; 
}; 

(. Qui ne peut pas être C++ tout à fait légal, pirater en fonction de votre compilateur)

Oh, même la version n'a pas besoin basé sur un modèle à utiliser les nouvelles. Déclarez simplement les données en tant que float data[W*H]; Le faire sortir du tas sera un plus grand coup de pouce de performance que «optimisant» un peu de maths.

0

Pas tellement une réponse complète, mais quelques informations qui peuvent aider (si vous n'êtes pas déjà au courant de ces derniers): Les deux OpenCV et Boost (uBLAS) ont de très bonnes implémentations de la matrice (rapide/complet/fonctionnalités complètes). Je n'ai pas regardé à l'intérieur d'eux pour voir comment ils mettent/get des éléments ou redimensionnent après l'instanciation cependant.