SORU
2 Mart 2011, ÇARŞAMBA


Nasıl daha iyi performans İOStream almak için?

Çoğu daha önce C-kullanıcılar fonksiyonlarıprintf / scanf Aile C bile kullanmayı tercih eder .

Arayüz çok daha iyi (özellikle POSIX-gibi biçim ve yerelleştirme) bulduğumu itiraf etmeliyim rağmen, ezici bir endişe performans gibi görünüyor.

At alma sorusuna bak:

How can I speed up line by line reading of a file

En iyi cevap fscanf... ve C ifstream sürekli x2-x3 kat daha yavaş gerçekleşiyor gibi görünüyor.

Eğer "ipucu" İOStreams performansını artırmak için: iş, ne değildir. bir depo derleme etsek çok iyi olur diye düşündüm

Yansıma olan Pists

  • tamponlama (6**?)
  • eşitleme (7**?)
  • (kesilmiş-aşağı yerel kullanabilir miyiz ? yerel taşıma Tamamen kaldırın ?)

Ve tabii ki, diğer yaklaşımlar bekliyoruz.

Not:" uygulama, Dietmar Chelsea tarafından, söz edildi, ama bu konuda fazla ayrıntıya yerini bulamadım. önceki başvurular ölü bir bağlantı gibi görünüyor. "yeni bir

CEVAP
2 Mart 2011, ÇARŞAMBA


Şimdiye kadar topladım:

Tampon:

Eğer varsayılan arabellek çok küçük ise, arabellek boyutunun artırılması kesinlikle performansını artırabilirsiniz:

  • HDD isabet sayısını azaltır
  • sistem çağrıları azaltır

Buffer streambuf temel uygulama erişerek ayarlanabilir.

char Buffer[N];

std::ifstream file("file.txt");

file.rdbuf()->pubsetbuf(Buffer, N);
// the pointer reader by rdbuf is guaranteed
// to be non-null after successful constructor

Nezaket @iavr uyarı: cppreference göre en iyi dosya açmadan önce pubsetbuf Ara. Çeşitli standart kütüphane uygulamaları aksi takdirde farklı davranışları var.

İşleme Ayar:

Yerel karakter dönüştürme, filtreleme, ve sonra sayılar ve tarihler söz konusu olduğunda daha zekice bir hile yapabilirsiniz. Gönderme ve sanal dinamik aramalar karmaşık bir sisteme geçmesi, cezası düzeltmek yardımcı olabilir kaldırma çarptı.

C varsayılan ayar herhangi bir dönüştürme işlemi gibi makineler boyunca eşit olmak için değil. Kullanmak için iyi bir varsayılan.

Senkronizasyon:

Herhangi bir performans geliştirme bu tesisi kullanan göremedim.

Bir ulaşılabiliyorglobalayarı (std::ios_base statik üyesi) sync_with_stdio statik fonksiyonunu kullanarak.

Ölçümler:

Bu oyun, basit bir program ile eğlendi, -O2 ile SUSE 10p3 gcc 3.4.2 kullanarak derledik.

C : 7.76532 e 06
C : 1.0874 e 07

Varsayılan kod 20%... hakkında bir yavaşlama gösterir. Aslında tampon (C veya C ) veya senkronizasyon parametreleri (C ) ile müdahale herhangi bir iyileşme sağlayamadı.

Başkaları tarafından sonuçlar:

@G 4.7.2-2ubuntu1, -O3, sanal Ubuntu 11.10, 3.5.0-25-generic, x86_64, yeterli ram/cpu, 196MB birkaç İrfy >largefile.txt" çalışır

C : 634572 C : 473222

C25% daha hızlı

@4.4.5, -O3, g Ubuntu Matteo Italia 180 MB rasgele bir dosya ile 10.10 x86_64 Linux

C : 910390
C : 776016

C17% daha hızlı

@G Bogatyr-apple-darwin10-i686 g (GCC) -4.2.1 4.2.1 (Apple Inc. 5664 inşa), 4 GB ram, mac mini, 168MB bir veri dosyası ile bu test dışında boşta

C : 4.34151 e 06
C : 9.14476 e 06

C111% daha yavaş

Cevap: uygulama kalitenin bir çok platformda: / bağlı

İşte o kıyaslama ilgilenenler için tam kod:

#include <fstream>
#include <iostream>
#include <iomanip>

#include <cmath>
#include <cstdio>

#include <sys/time.h>

template <typename Func>
double benchmark(Func f, size_t iterations)
{
  f();

  timeval a, b;
  gettimeofday(&a, 0);
  for (; iterations --> 0;)
  {
    f();
  }
  gettimeofday(&b, 0);
  return (b.tv_sec * (unsigned int)1e6   b.tv_usec) -
         (a.tv_sec * (unsigned int)1e6   a.tv_usec);
}


struct CRead
{
  CRead(char const* filename): _filename(filename) {}

  void operator()() {
    FILE* file = fopen(_filename, "r");

    int count = 0;
    while ( fscanf(file,"%s", _buffer) == 1 ) {   count; }

    fclose(file);
  }

  char const* _filename;
  char _buffer[1024];
};

struct CppRead
{
  CppRead(char const* filename): _filename(filename), _buffer() {}

  enum { BufferSize = 16184 };

  void operator()() {
    std::ifstream file(_filename, std::ifstream::in);

    // comment to remove extended buffer
    file.rdbuf()->pubsetbuf(_buffer, BufferSize);

    int count = 0;
    std::string s;
    while ( file >> s ) {   count; }
  }

  char const* _filename;
  char _buffer[BufferSize];
};


int main(int argc, char* argv[])
{
  size_t iterations = 1;
  if (argc > 1) { iterations = atoi(argv[1]); }

  char const* oldLocale = setlocale(LC_ALL,"C");
  if (strcmp(oldLocale, "C") != 0) {
    std::cout << "Replaced old locale '" << oldLocale << "' by 'C'\n";
  }

  char const* filename = "largefile.txt";

  CRead cread(filename);
  CppRead cppread(filename);

  // comment to use the default setting
  bool oldSyncSetting = std::ios_base::sync_with_stdio(false);

  double ctime = benchmark(cread, iterations);
  double cpptime = benchmark(cppread, iterations);

  // comment if oldSyncSetting's declaration is commented
  std::ios_base::sync_with_stdio(oldSyncSetting);

  std::cout << "C  : " << ctime << "\n"
               "C  : " << cpptime << "\n";

  return 0;
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • fufko

    fufko

    27 ŞUBAT 2006
  • New Scientist

    New Scientis

    27 Kasım 2006
  • TheDailyTechDose

    TheDailyTech

    15 EKİM 2012