2013-01-23 31 views
6

Grafik dosya formatı için basit bir okuyucu ve ayrıştırıcı yazdım. Sorun, inanılmaz derecede yavaş olmasıdır. İşte alakalı yöntemler şunlardır: o kadar yavaş olmasının nedeniKilitleme neden bu sıralı dosya ayrıştırıcısını yavaşlatıyor?

Graph METISGraphReader::read(std::string path) { 
    METISParser parser(path); 
    std::pair<int64_t, int64_t> header = parser.getHeader(); 
    int64_t n = header.first; 
    int64_t m = header.second; 

    Graph G(n); 

    node u = 0; 
    while (parser.hasNext()) { 
     u += 1; 
     std::vector<node> adjacencies = parser.getNext(); 
     for (node v : adjacencies) { 
      if (! G.hasEdge(u, v)) { 
       G.insertEdge(u, v); 
      } 
     } 
    } 
    return G; 
} 

std::vector<node> METISParser::getNext() { 
    std::string line; 
    bool comment = false; 
    do { 
     comment = false; 
     std::getline(this->graphFile, line); 
     // check for comment line starting with '%' 
     if (line[0] == '%') { 
      comment = true; 
      TRACE("comment line found"); 
     } else { 
      return parseLine(line); 
     } 

    } while (comment); 
} 

static std::vector<node> parseLine(std::string line) { 
    std::stringstream stream(line); 
    std::string token; 
    char delim = ' '; 
    std::vector<node> adjacencies; 

    // split string and push adjacent nodes 
    while (std::getline(stream, token, delim)) { 
     node v = atoi(token.c_str()); 
     adjacencies.push_back(v); 
    } 
    return adjacencies; 
} 

teşhis için ben bir profil (Elma Instruments) içinde koştu. Sonuçlar şaşırtıcıydı: Havai kilitleme nedeniyle yavaş. Program, zamanının% 90'ından fazlasını pthread_mutex_lock ve _pthread_cond_wait'da geçirir.

Instruments

Ben kilitleme havai gelen hiçbir fikrim yok, ama ondan kurtulmak gerekir. Bir sonraki adımlar önerebilir misin?

DÜZENLEME: _pthread_con_wait için genişletilen çağrı yığınına bakın.

enter image description here

+0

istream kullanımlarını getline bir sürümüdür. Neden stdin'den okudum sanıyorsun? – clstaudt

+0

Çünkü ben bir düğmedir. –

+0

Hmm, (Neden) kodunuzu OpenMP'ye bağlarsınız? Log4cxx bu bağımlılığı getirir mi? –

cevap

2

_pthread_cond_wait çağrı yığını genişletin ve pthread_mutex_lock kilitleme çağrılar çağrılması nerede olduğunu öğrenmek için çağırır: Bu bakarak kilitleme yükü kaynağını anlamaya olamaz.

Tahmini olarak, yaptığınız tüm gereksiz yığın ayırmalarda olduğunu söyleyeceğim. Yığın, güvenli bir kaynaktır ve bu platformda iplik güvenliği, muteksler yoluyla sağlanabilir.

+1

Yukarıdaki genişletilmiş çağrı yığına bir göz atın. Gereksiz yığın ayırmayı nerede yaparım? – clstaudt

+0

Kilitleme, burada sunduğunuz kodun dışında olan OpenMP çerçevesinde yapılır. Oluşturduğunuz geçici dizeler ve vektörler açısından gerekenden daha fazla tahsis yapıyorsunuz, ancak OpenMP'de yaptığınız her şeye kıyasla küçük patatesler. – karunski

+0

"Oluşturduğunuz geçici dizeler ve vektörler açısından gerekenden daha fazla tahsis yapıyorsunuz" Muhtemelen, ancak bu tahsisler yığında yer alıyor, değil mi? – clstaudt

1

istream'dan verileri okuyan tüm işlevler, streambuf numaralı telefondan mutex, okuma verilerini kilitleyecek ve mutex'un kilidini açacaktır. Bu ek yükü ortadan kaldırmak için, dosyayı istream yerine streambuf doğrudan okuyun ve verileri ayrıştırmak için stringstream kullanmayın. İşte

Ben bir dosya, bir `std :: ifstream` okunan streambuf yerine @KonradRudolph

bool fastGetline(streambuf* sb, std::string& t) 
{ 
    t.clear(); 
    for(;;) { 
     int c = sb->sbumpc(); 
     switch (c) { 
     case '\n': 
      return true; 
     case '\r': 
      if(sb->sgetc() == '\n') 
       sb->sbumpc(); 
      return true; 
     case EOF: 
      return !t.empty(); 
     default: 
      t += (char)c; 
    } 
} 
+0

Bu mantıklı. Ayrıcamı yarın 'fastGetline' kullanarak uygulamaya çalışacağım ve işe yarayıp yaramadığını göreceğiz. – clstaudt

+0

Eğer bir '' r 'değil ** sonra ** bir' 'nn' ise, 'fastGetline' yine de sona erer. Bu '' r '' push_back ve okumaya devam etmek daha iyi olacağını inanıyorum. Her ne kadar tek başına '' \ r''s işlemek bir yargılama meselesidir. Her nasılsa ilginç bir cevap. – Ali

+0

@Ali Standalone '' r', yaklaşık on yıl öncesine kadar Mac’te satır sonu olarak kullanıldı. – user763305

İlgili konular