50 votes

Quelle est la méthode la plus rapide pour les E / S de fichiers séquentielles hautes performances en C ++?

En supposant que les suivantes pour...
Sortie:
Le fichier est ouvert...
Les données sont 'streaming' sur le disque. Les données en mémoire dans une grande mémoire tampon contiguë. Il est écrit sur le disque dans sa forme brute, directement à partir de la mémoire tampon. La taille de la mémoire tampon est configurable, mais fixe pour la durée du cours d'eau. Les tampons sont écrites dans le fichier, l'un après l'autre. Pas d'opérations de recherche sont menées.
...le fichier est fermé.

Entrée:
Un gros fichier (par écrit comme ci-dessus) est lu à partir du disque du début à la fin.


Là généralement acceptée des lignes directrices pour la réalisation la plus rapide possible séquentielle e/S de fichier en C++?

Certaines considérations possibles:

  • Lignes directrices pour le choix optimal taille de la mémoire tampon
  • Une bibliothèque portable comme boost::asio être trop abstraite pour exposer les subtilités d'une plate-forme spécifique, ou peut-il être considéré optimal?
  • Est asynchronous I/O toujours préférable d'synchrone? Que faire si la demande n'est pas contraire au CPU?

Je me rends compte que ce sera la plate-forme des considérations spécifiques. Je salue les orientations générales ainsi que celles particulières pour les plates-formes.
(mon plus intérêt immédiat dans Win x64, mais je suis intéressé par les commentaires sur Solaris et Linux)

32voto

quark Points 7773

Là généralement acceptée des lignes directrices pour la réalisation la plus rapide possible séquentielle e/S de fichier en C++?

Règle 0: Mesure. Utiliser tous les outils de profilage et de les faire connaître. C'est presque un commandement dans la programmation que si vous n'avez pas le mesurer, vous ne savez pas comment il est rapide, et, pour I/O c'est encore plus vrai. Assurez-vous de test dans des conditions de travail réelles , si vous le pouvez. Un processus qui n'a pas de compétition pour le système d'e/S peut être plus optimisé, optimisé pour des conditions qui n'existent pas dans les charges.

  1. L'utilisation de la mémoire mappée à la place de l'écriture dans des fichiers. Ce n'est pas toujours plus rapide, mais il permet la possibilité d'optimiser les I/O dans un système d'exploitation spécifique, mais relativement mobiles, en évitant la copie inutile, et, profitant de l'OS, de la connaissance de la façon dont le disque en cours d'utilisation. ("Portable" si vous utilisez un wrapper, pas un OS spécifique les appels de l'API).

  2. Essayez et linéariser votre sortie autant que possible. Avoir à sauter autour de la mémoire pour trouver les tampons d'écriture peut avoir des effets notables dans des conditions optimisées, car les lignes de cache, de pagination et d'autres sous-système de mémoire questions vont commencer à la matière. Si vous avez beaucoup de tampons de regard sur le support de scatter-gather I/O qui essaie de faire linéarisant pour vous.

Certaines considérations possibles:

  • Lignes directrices pour le choix optimal taille de la mémoire tampon

Taille de la Page pour les débutants, mais être prêt pour l'affiner.

  • Une bibliothèque portable comme boost::asio être trop abstraite pour exposer les subtilités d'une plate-forme spécifique, ou peut-il être considéré optimal?

Ne supposez pas qu'il est optimal. Cela dépend complètement de la médiathèque est exercée sur votre plate-forme, et des efforts que les développeurs ont mis en le rendant encore plus rapide. Après avoir dit que un portable bibliothèque d'e/S peut être très rapide, parce que la vitesse des abstractions existent sur la plupart des systèmes, et il est généralement possible de venir avec un général de l'API qui couvre un grand nombre de bases. Coup de pouce.Asio est, au meilleur de mes connaissances limitées, assez affiné pour la plate-forme en particulier, il est sur: il y a toute une famille d'OS et OS-variante des Api spécifiques pour rapide d'e/S asynchrone (par exemple, epoll, /dev/epoll, kqueue, Windows overlapped I/O), et Asio les enveloppe tous.

  • Est asynchronous I/O toujours préférable d'synchrone? Que faire si la demande n'est pas contraire au CPU?

Asynchronous I/O n'est pas plus rapide dans un raw de sens que synchrone I/O. Ce asynchronous I/O n'est de vous assurer que votre code n'est pas de perdre du temps d'attente pour les I/O pour valider. Il est plus rapide d'une manière générale que l'autre méthode de ne pas perdre de temps, à savoir l'utilisation de threads, car il sera de retour d'appel dans votre code lors de l'I/O est prêt et pas avant. Il n'y a pas de faux départs ou des préoccupations avec des threads inactifs qui ont besoin d'être résilié.

12voto

Marc Mutz - mmutz Points 10367

Un conseil général est de désactiver la mise en mémoire tampon et de lire/écrire en gros morceaux (mais pas trop grand, alors vous allez perdre trop de temps d'attente pour l'ensemble de l'I/O pour terminer dans les cas où vous pourriez commencer à grignoter à l'écart lors de la première mégaoctet déjà. Il est trivial de trouver le sweet spot avec cet algorithme, il n'y a qu'un seul bouton à tourner: la taille des morceaux).

Au-delà, pour l'entrée mmap()ing le fichier partagé en lecture seule et est (si pas le plus rapide, à l'époque) la manière la plus efficace. Appelez madvice() si votre plate-forme qu'il a, à dire le noyau de la façon dont vous allez parcourir le fichier, donc il peut faire readahead et jetez les pages par la suite au plus vite.

Pour la sortie, si vous disposez déjà d'un tampon, d'envisager de le soutenir avec un fichier (avec un mmap()), de sorte que vous n'avez pas à copier les données dans l'espace utilisateur.

Si mmap() n'est pas à votre goût, puis il y a fadvice(), et, pour la très difficiles, async fichier I/O.

(Tous les ci-dessus est POSIX, Windows les noms peuvent être différents).

7voto

Michael McCloskey Points 1765

Pour Windows, vous voudrez vous assurer que vous utilisez la FILE_FLAG_SEQUENTIAL_SCAN dans votre CreateFile() l'appel, si vous optez pour l'utilisation de la plateforme spécifique de l'API Windows. Cela permettra d'optimiser la mise en cache pour les I/O. autant Que la taille du buffer de go, taille de la mémoire tampon qui est un multiple du disque de la taille des secteurs est généralement conseillé. 8K est un bon point de départ avec peu d'avantages à aller plus.

Cet article traite de la comparaison entre async et de la fonction de synchronisation de Windows.

http://msdn.microsoft.com/en-us/library/aa365683(SV.85).aspx

3voto

KPexEA Points 6188

Comme vous l'avez noté ci-dessus, tout dépend de la machine / du système / des bibliothèques que vous utilisez. Une solution rapide sur un système peut être lente sur un autre.

Une directive générale serait cependant d’écrire le plus grand nombre de morceaux possible.
L'écriture d'un octet à la fois est généralement la plus lente.

Le meilleur moyen de savoir avec certitude est de coder de différentes manières et de les profiler.

2voto

Marsh Ray Points 2012

Vous avez demandé sur le C++, mais il semble que vous êtes passé et prête à se faire un peu de plate-forme spécifique.

Sur Windows, FILE_FLAG_SEQUENTIAL_SCAN avec un fichier de mappage est probablement le moyen le plus rapide. En fait, votre processus de sortie avant que le fichier est sur le disque. Sans explicitement de blocage opération de vidage, il peut prendre jusqu'à 5 minutes pour Windows permettant de commencer à écrire ces pages.

Vous devez être prudent si les fichiers ne sont pas sur les périphériques locaux, mais un lecteur réseau. Réseau des erreurs apparaissent comme SEH des erreurs, ce qui vous aurez besoin d'être préparé à gérer.

*Les nixes, vous pourriez obtenir un peu plus de performance d'écriture séquentielle d'un disque brut de l'appareil. Cela est possible sur Windows aussi, mais pas aussi bien pris en charge par l'Api. Cela permettra d'éviter un peu de système de fichiers dessus, mais il peut pas assez pour être utile.

Grosso modo, la RAM est plus de 1000 fois plus rapide que les disques, et le PROCESSEUR est plus rapide encore. Il y a probablement pas beaucoup de logique optimisations qui vont de l'aide, sauf en évitant les mouvements des têtes de disque (seek) chaque fois que possible. Un disque dédié juste pour ce fichier peut aider de manière significative ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X