Question Quel est le moyen le plus rapide de chatter plusieurs fichiers? [fermé]


Je me demande s'il existe un moyen de concaténer des fichiers texte unix plus rapidement que courir cat?

Voici le problème auquel je suis confronté. Je suis une chaîne de traitement d'un fichier texte ~ 100G dans Taille. J'essaie d'améliorer le temps d'exécution en divisant le fichier en plusieurs centaines de plus petits fichiers et les traiter en parallèle. En fin de compte, je cat le résultat fichiers ensemble dans l'ordre. Le temps de lecture / écriture du fichier prend des heures. je aimerait trouver un moyen d'améliorer les éléments suivants:

cat file1 file2 file3 ... fileN >> newBigFile
  1. Cela nécessite de doubler l'espace disque comme file1 ... fileN prend 100G, et puis newBigFile prend encore 100Gb, puis file1... fileN obtient enlevé

  2. Les données sont déjà dans file1 ... fileN, faisant le cat >> encourt lire et écrire le temps où tout ce dont j'ai vraiment besoin est pour les centaines de fichiers à réapparaissent en 1 fichier ...


16
2017-11-01 19:25


origine


Réponses:


Si vous n’avez pas besoin d’un accès aléatoire au gros fichier final (c’est-à-dire que vous venez de le lire une fois du début à la fin), vous pouvez faire apparaître des centaines de fichiers intermédiaires. Où tu ferais normalement

$ consume big-file.txt

au lieu de faire

$ consume <(cat file1 file2 ... fileN)

Cela utilise Unix substitution de processus, parfois aussi appelé "tubes nommés anonymes".

Vous pouvez également gagner du temps et de l’espace en divisant votre saisie et en effectuant le traitement en même temps; GNU Parallel a un --commutateur cela fera précisément cela. Il peut également réassembler les sorties en un seul gros fichier, en utilisant potentiellement moins d’espace de travail nombres de coeurs morceaux sur disque à la fois. Si vous exécutez littéralement vos centaines de processus en même temps, Parallel améliore considérablement votre efficacité en vous permettant de régler la quantité de parallélisme sur votre machine. Je le recommande fortement.


6
2018-06-27 19:03



Peut être dd serait plus rapide parce que vous n'auriez pas à passer des choses entre chat et la coquille. Quelque chose comme:

mv file1 newBigFile
dd if=file2 of=newBigFile seek=$(stat -c %s newBigFile)

5
2017-11-01 19:30



Solution rapide mais pas gratuite? Obtenez un disque SSD ou un stockage basé sur PCIe flash. Si cela doit être fait sur une base régulière, augmenter la vitesse des E / S disque sera la solution la plus rentable et la plus rapide possible.


4
2017-11-01 19:27



Est-il possible que vous ne divisiez pas simplement le fichier? Au lieu de cela, traitez le fichier en morceaux en définissant le pointeur de fichier dans chacun de vos travailleurs parallèles. Si le fichier doit être traité de manière orientée ligne, cela complique les choses, mais cela peut toujours être fait. Chaque travailleur doit comprendre que plutôt que de commencer au décalage que vous lui donnez, il doit d'abord rechercher l'octet par octet dans la nouvelle ligne suivante +1. Chaque agent doit également comprendre qu'il ne traite pas la quantité d'octets définie, mais traite la première ligne après la quantité d'octets allouée à traiter.

L'allocation et la configuration réelles du pointeur de fichier sont assez simples. S'il y a n travailleurs, chacun traite des octets de taille n / fichier et le pointeur de fichier commence au numéro de travail * n / file_size.

Y a-t-il une raison pour laquelle ce type de plan n'est pas suffisant?


4
2017-11-01 21:18



Lors de la concaténation de fichiers, vous pouvez supprimer les petits fichiers à mesure qu'ils sont ajoutés:

for file in file1 file2 file3 ... fileN; do
  cat "$file" >> bigFile && rm "$file"
done

Cela éviterait d'avoir à doubler l'espace.

Il n'y a pas d'autre moyen de faire des fichiers magiquement concaténés. L'API du système de fichiers n'a tout simplement pas de fonction qui fait cela.


4
2017-11-01 21:24



Je crois que c'est le moyen le plus rapide de capturer tous les fichiers contenus dans le même dossier:

$ ls [path to folder] | while read p; do cat $p; done

3
2017-09-02 17:02



Il y a une telle chose comme trop de concurrence.

Une meilleure façon de le faire serait d'utiliser des lectures à accès aléatoire dans le fichier sur les plages souhaitées et de ne jamais les diviser et traiter uniquement le nombre de fichiers en tant que nombre de processeurs / cœurs physiques dans la machine. C'est-à-dire que si le disque ne contient pas d'IOPS, vous devez réduire le disque jusqu'à ce qu'il ne soit plus le goulot d'étranglement.

Ce que vous faites de toute façon avec toute la division / copie / suppression naïve génère des tonnes d'IOPS et il n'y a aucun moyen de contourner la physique.

Une solution transparente qui nécessiterait probablement plus de travail que ce qui en vaut la peine, à moins qu'il ne s'agisse d'un problème / problème quotidien lié à l'écriture d'un système de fichiers FUSE personnalisé représentant un seul fichier sous la forme de plusieurs fichiers. Il y a beaucoup d'exemples sur le traitement des fichiers d'archive en tant que fichiers individuels qui vous montreront comment procéder.


2
2018-06-27 19:16



tout ce dont j'ai vraiment besoin, c'est que les centaines de fichiers réapparaissent en 1 fichier ...

La raison pour laquelle il n'est pas pratique de joindre des fichiers de cette façon au niveau du système de fichiers, car les fichiers texte ne remplissent généralement pas exactement un bloc de disque, les données des fichiers suivants doivent donc être déplacées pour combler les lacunes. tas de lectures / écrit en tous cas.


1
2017-11-01 19:41