10
votes

STD :: Vecteur et Tableaux de style C

J'essaie d'expérimenter avec opencl pour augmenter la vitesse de notre logiciel. Nous travaillons beaucoup avec des cartes et, pour simplifier, représenter une carte en tant que std :: vecteur . L'API Opencl prend des pointeurs de style C cru comme des arguments, par exemple INT * dans l'affaire ci-dessus.

Mes questions:

  • Y a-t-il des garanties de mise en œuvre dans la STL que le vecteur est, en interne, consécutif en mémoire?
  • Puis-je lancer en toute sécurité une STD :: Vector to int * et vous attendez à ce que cela fonctionne?
  • Dans le cas d'un vecteur de vecteurs, puis-je quand même supposer que cela détient vrai? Je m'attendrais à ce que le vecteur conserve d'autres données de l'état ou des problèmes d'alignement, ou peut-être quelque chose d'autre ...
  • Quelle est la meilleure façon de contacter cela? Écrivez une structure de données 2D personnalisée qui contient un tampon interne et contigu à la mémoire et fonctionne avec cela? Je devrais copier / depuis des vecteurs beaucoup ...

    merci.


2 commentaires

Vous pouvez également être intéressé par cette question: Stackoverflow.com/Questtions/1339470/...


Notez que vecteur est une exception à la règle informit.com/guides/content.aspx?g=cplusplus&seqnum=98


4 Réponses :



18
votes

Y a-t-il des garanties de mise en œuvre dans la STL que le vecteur est, en interne, consécutif en mémoire?

AS de C ++ 03, oui, un vecteur est garanti d'utiliser un stockage contigu. (En C ++ 98, une lacune accidentelle a donc été une échappatoire accidentelle afin qu'une mise en œuvre puisse utiliser hypothétiquement un stockage non contigu, mais elle a été fixée dans la révision de 2003 de la norme - et aucune mise en œuvre utilisée non contiguës non contiguës stockage parce que ce serait une idée terrible)

Puis-je lancer en toute sécurité un STD :: Vector to Int * et vous attendez à ce que cela fonctionne?

La voie habituelle est & v [0] . ( & * v.begin () fonctionnerait probablement aussi, mais je semble me rappeler qu'il y a un libellé moelleux dans la norme qui ne rend pas 100% fiable)

non. Pourquoi vous attendriez-vous que cela fonctionne? Un vecteur est une classe. Ce n'est pas un pointeur. Il suffit contient un pointeur.

Dans le cas d'un vecteur de vecteurs, puis-je quand même supposer que cela détient vrai? Je m'attendrais à ce que le vecteur conserve d'autres données de l'état ou des problèmes d'alignement, ou peut-être quelque chose d'autre ...

Le vecteur se comporte la même chose que vous le stockez. Si vous faites un vecteur de vecteurs, vous vous retrouvez avec un objet qui contient un pointeur sur un tableau alloué en tas, où chaque élément est un objet qui contient un pointeur sur un tableau alloué en tas.

Quant à la façon dont vous devriez approcher cela, cela dépend de nombreux facteurs. Quelle est la taille de votre ensemble de données total? Vous voudrez peut-être avoir la table entière allouée contiguë. Avec un vecteur de vecteurs, chaque ligne est une allocation distincte.


5 commentaires

Merci. En effet j'ai formulé ma question mal, je voulais dire «lancer le premier élément au pointeur» plutôt que «vecteur de coulé», ou «adresse du vecteur lui-même». Quoi qu'il en soit, il semble qu'il n'ya aucun moyen de travailler facilement avec le contenu brut d'un vecteur de vecteurs, je devrai repenser la façon dont je travaille avec les données. La taille typique est comprise entre 500x500xsizeof (sans signé) et 2500x2500xsizeof (double), puis 20 à 50 de ceux-ci, si assez gros.


Boost.MultiArray ferait le travail pour vous gentiment. Alternativement, je voudrais simplement l'allouer comme un seul tableau contigu ou un vecteur assez grand pour contenir tout le tableau 2D.


Notez que vecteur est l'exception au cas que & v [0] donne un tableau de style C .


& * v.begin () ne fonctionne que si le tableau est non vide. (L'extrémité de dérivation () est un comportement indéfini et sur de nombreuses plateformes donnera une affirmation dans les constructions de débogage)


@pgast: La même chose est vraie pour & V [0].



5
votes
  • Y a-t-il des garanties de mise en œuvre dans la STL que vecteur est de
    Interne, consécutif en mémoire

    Oui, c'est une matrice dynamique. Standard garantit que les objets à l'intérieur du vecteur sont stockés consécutivement.

    • Puis-je lancer en toute sécurité une STD :: Vector to int * et vous attendez à ce que cela fonctionne?

      Non, mais vous pouvez utiliser commencer () et utiliser cela comme le pointeur.

      • Y a-t-il des garanties de mise en œuvre dans la STL que vecteur est,
        Interne, consécutif en mémoire

        Non, car le vecteur peut contenir des variables de membre internes, l'ensemble de la matrice 2D ne sera pas un emplacement de mémoire continue


1 commentaires

"Non, mais vous pouvez utiliser commencer () et utiliser cela comme le pointeur.", Ce n'est généralement pas vrai, et ne garantit certainement pas par la norme. Vous devriez toujours prendre l'adresse de l'itérateur déréférencé pour obtenir un pointeur, donc "& * v.begin ()" i.s..o. Juste "v.begin ()"



3
votes

Vous avez mentionné dans un commentaire avec laquelle vous travaillez avec 2500x2500xSIZEOF (Double) Données. Dans ce cas, je suggérerais d'utiliser un seul vecteur au lieu de vecteur de vecteurs. Allouer des éléments NXM dans un vecteur et enveloppez-le dans une classe exposant l'indexation bidimensionnelle si vous le souhaitez. Vous obtenez tous les avantages du vecteur avec une surcharge minimale et toutes vos données sont toujours en mémoire contiguë pour le traitement rapide.


1 commentaires

Oui, c'est probablement l'approche que je / que nous devrions prendre - du moins dans le contexte de cette question. Le problème est que nos types de données "Carte" doivent également être capables de lire à partir de différents emplacements (sur un réseau, du disque pour les cartes trop gros pour s'adapter à la mémoire (20 cartes GigaByte ne font pas exception), ... nous Il suffit de tester quelques approches, ou d'implémenter plusieurs et d'un mécanisme de sélection de temps d'exécution qui détermine le comportement optimal de la machine / des problèmes de l'utilisateur. Quoi qu'il en soit, merci pour votre commentaire.