6
votes

Initialiser un vecteur Ublas d'un tableau C

J'écris une extension MATLAB à l'aide de la bibliothèque C ++ Ublas, et j'aimerais pouvoir initialiser mes vecteurs Ublas des tableaux C passés par le Matlab Interpeter. Comment puis-je initialiser le vecteur Ublas d'un tableau C sans (pour l'efficacité) copiant explicitement les données. Je cherche quelque chose sur les lignes de code suivantes: xxx

en général, est-il possible d'initialiser un C ++ std :: vecteur d'un tableau? Quelque chose comme ceci: xxx

mais où l'initialisation ne copierait pas les données. Dans ce cas, la sortie est xxx

mais je veux que la sortie soit la même, où la mise à jour de la matrice C modifie les données pointées par le vecteur C ++ < Pré> xxx


0 commentaires

6 Réponses :


4
votes

Vous pouvez initialiser un std :: Vecteur d'un tableau C Facilement:

vector<int> v(pv, pv+10);


2 commentaires

Merci pour votre réponse, mais cela copierait les données. Je veux V et pv pour pointer sur le même bloc de données.


Vous ne pouvez pas avoir ça. std :: vecteur possède toujours sa mémoire. Vous pouvez écrire votre propre classe de vecteur si ...



6
votes

Les deux std :: vecteur et ublas :: vecteur sont des conteneurs. L'ensemble des conteneurs est de gérer le stockage et les vies de leurs objets contenus. C'est pourquoi, lorsque vous les initialisez, ils doivent copier des valeurs en stockage qu'ils possèdent.

C Les tableaux sont des zones de mémoire fixées en taille et en emplacement, de sorte que vous ne pouvez obtenir leurs valeurs que dans un conteneur en copiant.

Vous pouvez utiliser des tableaux C comme entrée de nombreuses fonctions d'algorithme afin que vous puissiez peut-être le faire pour éviter la copie initiale?


1 commentaires

Sauf que dans la théorie vous pouvez créer une sous-classe de Ublas :: Vecteur qui a fait cela. Votre sous-classe pourrait se comporter en tant que const Ublas :: Vecteur qui ne pourrait jamais être redimensionné, sinon vous devez remplacer toutes les méthodes impliquées dans le redimensionnement du conteneur pour assurer que la mémoire ne vous libère pas. . Seul un masochiste complet tenterait ceci.



8
votes

Je ne sais pas comment votre question concerne Matlab / Mex, mais une note latérale, vous voudrez peut-être savoir que MATLAB met en œuvre une stratégie Copy-on-écriture forte>.

Ceci signifie Que lorsque vous copiez un tableau par exemple, seuls certains en-têtes sont en réalité copiés, tandis que les données elles-mêmes sont partagées entre les deux tableaux. Et une fois que l'un d'entre eux est modifié, une copie des données est réellement faite. P>

Ce qui suit est une simulation de ce qui pourrait se passer sous la hotte (emprunté à partir de ce Old Post ): P>

-----------------------------------------
>> a = [35.7 100.2 1.2e7];

 mxArray a
    pdata -----> 35.7 100.2 1.2e7
  crosslink=0

-----------------------------------------
>> b = a;

 mxArray a
    pdata -----> 35.7 100.2 1.2e7
  crosslink     / \
    |  / \       |
    |   |        |
    |   |        |
   \ /  |        |
   crosslink     |
 mxArray b       |
    pdata --------

-----------------------------------------
>> a(1) = 1;

mxArray a
    pdata -----> (1) 100.2 1.2e7
  crosslink=0


   crosslink=0
 mxArray b
    pdata ------> 35.7 100.2 1.2e7 ...


6 commentaires

Vous pouvez voir cette méta-données dans le format de réglage de la fenêtre de commande MATLAB avec le format Format Débog


Un point mineur sur votre diagramme - vous le faites ressembler à la pensée MATLAB crée une nouvelle copie des données, réaffecte B pour le pointer et la mutation des données A pointe vers. Ce qui arrive réellement, c'est qu'une nouvelle copie des données est créée et A est réaffectée pour le pointer, puis les nouvelles données sont mutées.


Cela n'a peu aucune pertinence pour la question. La question concerne C ++. Si vous utilisez des cours MATLAB, ils pourraient avoir des optimisations de temps compilation contre une copie redondante. Une fois que vous avez pris un pointeur cru, Matlab ne peut pas empêcher d'autres bibliothèques d'essayer de faire des copies inutiles. En fait, l'opération même de demander un pointeur brut déclenchera le MATLAB à effectuer une copie des paramètres d'entrée.


@Dimititry Downvote est assez juste car il ne répond pas à la question, je vais toujours garder cette réponse de 9 ans même si elle est légèrement pertinente ... Quant à votre dernière déclaration, je devrais vous corriger et dire qu'à la Mex-API Niveau, MATLAB ne crée pas de copie lorsque vous demandez les données brutes d'un tableau numérique (c.-à-d. MXGETDATA et similaire). Bien sûr, cela ne vous empêche pas de faire des copies en enveloppant le pointeur brut à l'intérieur d'un std :: vecteur .


Eh bien, pour être honnête, mes expériences proviennent d'octave, que Google a tendance à rediriger vers Matlab répond de toute façon. En fournissant un pointeur de mémoire RAW MATLAB \ Contenants de tableau d'octave Abondez toute commande qu'ils avaient sur l'accès à la mémoire et afin de garantir que les effets secondaires ne seront pas causés par l'utilisation de ce pointeur, ils doivent s'assurer que la mémoire n'est pas partagée par d'autres objets. . Octave le fait-il sur la demande de pointeur, sauf si vous poivrez tout avec des modificateurs const . Le compilateur Matlab Mex pourrait être plus élaboré et tracer l'utilisation du pointeur ou non.


@Dimititry Nope, le Mex-Api, il vous permet tout simplement le pointeur et c'est à vous de ne pas vous tirer dessus dans le pied :)



2
votes

Voici quelques fonctions pour une affectation syntaxiquement pratique (certes ininitialisation): xxx

Les fonctions: xxx


0 commentaires

4
votes

Il existe deux classes non documentées dans Ublas Storage.HPP. Vous pouvez modifier la classe de stockage par défaut (non bornée_array) dans Ublas :: Vecteur de l'un d'entre eux.

  • La première classe, Array_Adaptor, effectue une copie de vos données lorsque Ublas :: Appels vectoriels vers Copy Constructor, pas du tout très utile. Je préférerais simplement le constructeur approprié pour le faire dans des classes sans bordure ou bornées.
  • La seconde, peu profonde_array_adaptor , déposez uniquement une référence de vos données, vous pouvez donc utiliser Vector pour modifier directement votre tableau C. Malheureusement, il a quelques bugs, lorsque vous attribuez une expression, il perd son pointeur de données d'origine. Mais vous pouvez créer une classe dérivée qui corrige ce problème.

    Ici le patch et un exemple: xxx

    sortie: xxx


0 commentaires

3
votes

La suggestion habituelle d'utiliser un adaptateur de réseau peu profond semble être une sorte de sarcastique pour moi - de pouvoir simplement accéder à un tableau via un pointeur que vous êtes censé la mettre dans un partage_array avec tout le comptage de référence Shebang (qui ne vient rien , puisque vous ne possédez pas le tableau) et de plus en plus avec un cauchemar d'aliasing de données. En réalité, Ublas a une implémentation à part entière de stockage ( array_adaptor code>) qui permet d'utiliser des vecteurs avec des tableaux C externes. La seule prise est un constructeur de vecteur qui en fait une copie. Pourquoi cette belle fonctionnalité n'est pas utilisée dans la bibliothèque, mais de toute façon, nous pouvons utiliser une petite extension (c'est en fait 2 lignes de code entourées de gonflement C ++ habituel)

int i[] = {1, 4, 9, 16, 25, 36, 49};
extarray_vector<int> iv(i);
BOOST_ASSERT_MSG(i == &iv[0], "Vector should attach to external array\n");
iv[3] = 100;
BOOST_ASSERT(i[3] == 100);
iv.resize(iv.size() + 1, true);
BOOST_ASSERT_MSG(i != &iv[0], "And detach from the array on resize\n");
iv[3] = 200;
BOOST_ASSERT(i[3] == 100);
iv.data().resize(7, i, 0);
BOOST_ASSERT_MSG(i == &iv[0], "And attach back to the array\n");
BOOST_ASSERT(i[3] == 200);


0 commentaires