2010-06-15 14 views
0

Je suis en train de transférer mes fichiers entre 2 clusters UNIX, les données sont purement numériques (vecteurs de double) sous forme binaire. Malheureusement l'un des systèmes est IBM ppc997 et l'autre est AMD Opteron, il semble que le format des nombres binaires dans ces systèmes sont différents.transférer des fichiers binaires entre les systèmes

J'ai essayé 3 façons jusqu'à présent:

1- Changé mes fichiers au format ASCII (par exemple enregistré un numéro à chaque ligne dans un fichier texte), les a envoyés à la destination et les changer à nouveau en binaire sur le système cible (les deux sont UNIX, pas de fin de la différence de caractère de ligne ??!)

2- Sent binaires purs à la destination

3- utilisé uuencode les a envoyés à la destination et les décoder

Malheureusement l'un de ces Les méthodes ne fonctionnent pas (mon code dans le système de destination génère des erreurs, alors qu'il fonctionne sur le premier système, je suis sûr à 100% que le code lui-même est portable). Je ne sais pas ce que je peux faire d'autre? Avez-vous une idée? Je ne suis pas un professionnel, s'il vous plaît ne pas utiliser la terminologie informatique! Et: mes codes sont en C, donc par binaire je veux dire une correspondance un à un entre la mémoire et le disque dur.

Merci

Répondre

2

La méthode 1 devrait fonctionner. Créez simplement un vecteur de test avec les valeurs 1, 2, ..., 10 et envoyez-le. Vous pouvez lire l'ascii qui a été créé (ainsi vous pouvez valider 'export') et donc aussi vérifier l'étape 'import' de relire le fichier. Vous pouvez perdre de la précision de cette façon, mais cela devrait vous rendre opérationnel.

La méthode 2 fonctionnera une fois que vous utiliserez une bibliothèque telle que XDR qui traite de l'endianness différent. Ces choses avaient l'habitude d'être un plus gros problème «il y a longtemps» et il y a des solutions. Ceci est par exemple comment un système comme R vous permet de partager des fichiers binaires entre architectures.

La méthode 3 n'est pas nécessaire sauf si vous faites quelque chose de vraiment gênant lors du transfert du fichier.

+0

Merci, mais il semble que les binaires dépendent des architectures, je ne suis pas un informaticien, mais je me souviens de mon premier cycle qu'il existe différentes façons de sauvegarder le signe d'un nombre à virgule flottante. Est-ce que XDR fonctionne maintenant? Où puis-je le trouver? – tim

+1

XDR est une bibliothèque d'encodage de Sun, essayez googleing pour 'xdr library' qui vient d'avoir un certain nombre de hits. L'exportation Ascii (méthode 1) n'en aura pas besoin. Exportez un ensemble de nombres connus vers ASCII, vérifiez le fichier. Importer à partir de ce fichier, vérifiez à nouveau. Lorsque vous avez ce travail, utilisez-le sur vos données réelles. –

0

Les solutions 2 et 3 ne fonctionneront généralement pas car différents processeurs peuvent utiliser différentes représentations internes de vos nombres. Pour les entiers, pas float/double, vous pouvez vous en sortir avec quelque chose qui prend soin de l'ordre des octets de vos différentes machines. Les représentations à virgule flottante sont beaucoup plus compliquées, et vous devrez rechercher en détail les représentations que vos différentes architectures utilisent. Mais toujours pour le double, par exemple, il n'y a qu'une exigence minimale concernant la précision, et vous pourriez vous retrouver dans une situation où vous devriez tronquer à la plus petite représentation des deux. Ces problèmes n'ont pas grand chose à voir avec le système d'exploitation que vous utilisez (Unix ou non) mais avec la façon dont le matériel aime avoir des choses.

+0

Merci, donc il n'y a pas d'autre moyen? Avez-vous une idée de la raison pour laquelle la solution 1 ne fonctionne pas? Merci d'une manière ou d'une autre – tim

+0

La solution 1 devrait normalement fonctionner mais elle est relativement coûteuse (temps, bande passante). Pourquoi votre mise en œuvre particulière ne l'a pas fait, nous ne pouvons pas le savoir, vous ne nous avez pas donné les détails. –

2

Les détails fournis sont rares. Répondre au mieux de ma compréhension.

.. l'un des systèmes IBM est ppc997 et l'autre est AMD Opteron

Ancien régime général (*) utilise la présentation big-endian, plus tard - petit-boutiste. Read this.

(*) Cela dépend du système d'exploitation. Le POWER CPU d'IBM peut faire à la fois de petits et de gros endian, mais aucun système d'exploitation fonctionnant sur eux n'utilise le mode little-endian.

Normalement, pour la présentation binaire, on choisit une endianness et cela va avec la présentation binaire. Pour les trucs réseau, la présentation des nombres big-endian est une norme.

Cela signifie que tous les lieux qui font quelque chose comme ceci:

/* writing to binary */ 
int a = 1234; 
write(fd,&a,sizeof(a)); 
/* reading from binary */ 
int x; 
read(fd,&x,sizeof(x)); 

devrait être converti en quelque chose comme ceci:

/* writing to binary */ 
int a = htonl(1234); 
write(fd,&a,sizeof(a)); 
/* reading from binary */ 
int x; 
read(fd,&x,sizeof(x)); 
x = ntohl(x); 

Une autre approche consiste à enregistrer l'indicateur boutisme (par exemple écrire la magie et vérifier de l'autre côté: MAGIC = 0x12345678 v. MAGIC = 0x78563412) avec les données binaires, et appliquer la conversion seulement quand l'endianness diffère. Bien que cette approche est moins élégante et n'a pas de réels avantages, je suis au courant.

+0

merci beaucoup, je vais lire à ce sujet. – tim

+0

En fait, pour les choses de réseau * big-endian * est la norme. Il est même appelé "Network Byte Order". Et puisque l'OP utilise des types à virgule flottante, il y a plus que simplement l'endianness. – caf

+0

@caf, merci, faute de frappe. J'utilise généralement du big-endian exclusivement (principalement pour les fonctions standard ntoh/hton) donc je mélange l'endianness tout le temps. – Dummy00001

0

Tous les processeurs prenant en charge IEEE 754 ont la même représentation binaire pour les flottants (techniquement appelés simples) et les doubles. La seule différence sera dans l'endianness du processeur. La seule incompatibilité entre IBM PPC et AMD Opteron devrait donc être l'endianness des doubles.

Lorsque vous byteswap le double à partir du disque à la mémoire, NE LE FAITES PAS:

double swap(double a); // THIS IS NEVER THE RIGHT THING TO DO. 

passage dans le double en valeur peut passer dans des registres par à virgule flottante. Comme toutes les combinaisons de bits ne sont pas des doubles valides, le processeur peut convertir le double en un NaN, qui peut avoir une représentation binaire différente de la valeur transmise. Ceci est plus susceptible de se produire avec un double valide dans l'ordre endian opposé. . (Voir here pour une explication plus détaillée.)

En d'autres termes, passez le double que vous voulez byteswap comme un pointeur ou un tableau de caractères. (Un tableau de caractères devrait être le meilleur choix.)

+0

Les codes sont très intéressants, mais comme je peux le comprendre, c'est juste pour swapping-unswapping, bien, mais ce dont j'ai besoin est d'utiliser les données échangées sur le système de destination, alors que dans l'article il a été raisonnablement expliqué. ont également mentionné ici que l'utilisation de ces codes pour cet objectif est fausse. Merci de toute façon – tim

+0

@tim, Ce que je veux dire, c'est que vous pouvez byteswap double tout ce que vous voulez, mais ne passez pas double dans l'endianness opposé en double; passez-les comme un tableau de caractères. Alors allez-y et byteswap. – MSN

+0

Oh, merci, mais c'est compliqué, j'ai utilisé XDR à la place. Merci encore – tim

3

Le code n'est pas 100% portable si vous écrivez le contenu de la mémoire dans des fichiers.

Vous avez besoin de quelque chose appelé sérialisation. Ok, terme d'informatique, mais cela signifie essentiellement que vous obtenez vos données et les transformez en une séquence d'octets bien définie et documentée, qui peut être relue en mémoire plus tard par le même ou un autre programme. Cette séquence d'octets est indépendante de l'architecture et de la plate-forme.

La plupart des environnements Unix sont déjà dotés d'une implémentation XDR, qui fournit des routines pour la sérialisation des données.

Un exemple simple encodage 4 doubles à stdout (vous pouvez utiliser la redirection du shell, ou l'utilisation fopen() pour ouvrir un fichier au lieu de stdout):

XDR xdrs; 
double data[4] = { 1.0, 255.41, -357.1, 123.4 }; 
int i; 

xdrstdio_create(&xdrs, stdout, XDR_ENCODE); 
for (i = 0; i < 4; i++) 
    xdr_double(&xdrs, &data[i]); 

Maintenant, pour obtenir ces doubles arrière (de stdin) et les imprimer:

XDR xdrs; 
double data; 
int i; 

xdrstdio_create(&xdrs, stdin, XDR_DECODE); 
for (i = 0; i < 4; i++) { 
    xdr_double(&xdrs, &data); 
    printf("%g\n", data); 
} 

Vous pouvez coder et décoder des structures complexes à l'aide de XDR. C'était une manière très stupide d'envoyer quatre doubles dans un fichier, et généralement vous devriez plutôt utiliser xdr_array() pour lire/écrire des tableaux d'un type de données. Les mêmes commandes, dans le même ordre, doivent être exécutées lors de l'enregistrement et lors du chargement du fichier.En fait, vous pouvez utiliser rpcgen pour générer automatiquement des structures C et leurs fonctions xdr correspondantes.

+1

+1 pour l'exemple de code en utilisant XDR. – RBerteig

+0

Vraiment merci, ça marche! – tim

Questions connexes