SORU
4 Aralık 2010, CUMARTESİ


C performans meydan: tamsayı std::string dönüştürme

Kimse benim tamsayı performansını yenmek için std::string kod, aşağıda bağlantısı?

Zaten C std::string, this one) gibi bir tamsayı dönüştürmek için nasıl açıklayan pek çok soru var ama çözümleri sağlanan hiçbiri verimli.

Burada bazı genel yöntemler, karşı yarışmak için bir derleme hazır kod:

  • "C" kullanarak stringstream: *19.*
  • SO-ers genellikle performans bilinçli tavsiye ederim sprintf,: http://ideone.com/82kwR

21*, boost::lexical_cast *aksine kendi uygulaması (white paper) ve stringstream ve sayısal ekleme operatörler kullanmaz. Gerçekten performansı this other question suggests that it's miserable çünkü karşılaştırıldığında, görmek istiyorum.

Ve masaüstü bilgisayarlarda rekabet ve gömülü sistemler üzerinde tam hızda çalışan bir yaklaşım gösterir, kendi katkısı olarak, algoritmalar tamsayı modül bağımlı aksine:

Eğer bu kodu kullanmak istiyorsanız, basitleştirilmiş BSD Lisansı altında kullanılabilir (ticari kullanıma izin verilen, atıf gerekli) yapacağım. Sadece soruyorum.

Son olarak, 4* *işlevi standart olmayan ama yaygın olarak kullanılabilir.

Cevap olarak benim performans ölçümleri kısa zamanda göndeririz.

Algoritmalar için kurallar

  • En azından bir ondalık içine 32-bit işaretli ve işaretsiz tam bir dönüşüm için kod sağlar.
  • std::string olarak çıktı üretir.
  • Diş çekme ve sinyalleri ile uyumlu olmayan hileler (örneğin, statik arabellekleri) hayır.
  • ASCII karakter kümesi varsayabiliriz.
  • Mutlak değer gösterilebilir bulunduğu iki a INT_MIN kodunuzu test etmek için emin makine tamamlayıcısı olacak.
  • İdeal olarak, bir çıkış olmalı karakter-için-karakteri ile özdeş kurallı C sürümünü kullanıyor stringstream, http://ideone.com/jh3Sa ama bir şey olduğu açıkça anlaşılır olarak doğru numara Tamam da.
  • YENİ: Derleyici ve iyileştirici seçenekleri tamamen devre dışı hariç) ne olursa olsun kullanabilirsiniz, ancak karşılaştırma için istediğiniz, kodu derlemek ve en az VC 2010 ve g altında doğru sonuçlar vermek gerekiyor .

Umut için Tartışma

Daha iyi algoritmalar yanı sıra, farklı platformlar ve Derleyiciler (hadi ölçü standart birim olarak MB/s işlem hacmi kullanın) bazı kriterler almak istiyorum. Sanırım bu kod benim için algoritma (biliyorum sprintf referans alır bazı kısayollar -- şimdi sabit) iyi tanımlanmış davranış standart, en azından altında ASCII varsayım, ama eğer gördüğünüz herhangi bir tanımsız davranış veya girdiler için çıktı geçersiz, lütfen gelin.

Sonuç:

Farklı algoritmalar her g ve VC2010, std::string farklı uygulamaları nedeniyle olası gerçekleştirin. VC2010 açıkça NRVO ile daha iyi bir iş, dönüş değeri gcc sadece yardım kurtulmak yok.

Kod büyüklük sırasına göre sprintf daha iyi performans bulundu. ostringstream arkasında 50 ve daha fazla bir faktör tarafından düşüyor.

Yarışmayı kazanan gcc benim kendi hızını 350% çalışan kod üreten user434507. Başka girdi YANİ toplum güçlükler nedeniyle kapandı.

Geçerli (final?) hız şampiyonu:

CEVAP
4 Aralık 2010, CUMARTESİ


#include <string>

const char digit_pairs[201] = {
  "00010203040506070809"
  "10111213141516171819"
  "20212223242526272829"
  "30313233343536373839"
  "40414243444546474849"
  "50515253545556575859"
  "60616263646566676869"
  "70717273747576777879"
  "80818283848586878889"
  "90919293949596979899"
};


std::string& itostr(int n, std::string& s)
{
    if(n==0)
    {
        s="0";
        return s;
    }

    int sign = -(n<0);
    unsigned int val = (n^sign)-sign;

    int size;
    if(val>=10000)
    {
        if(val>=10000000)
        {
            if(val>=1000000000)
                size=10;
            else if(val>=100000000)
                size=9;
            else 
                size=8;
        }
        else
        {
            if(val>=1000000)
                size=7;
            else if(val>=100000)
                size=6;
            else
                size=5;
        }
    }
    else 
    {
        if(val>=100)
        {
            if(val>=1000)
                size=4;
            else
                size=3;
        }
        else
        {
            if(val>=10)
                size=2;
            else
                size=1;
        }
    }
    size -= sign;
    s.resize(size);
    char* c = &s[0];
    if(sign)
        *c='-';

    c  = size-1;
    while(val>=100)
    {
       int pos = val % 100;
       val /= 100;
       *(short*)(c-1)=*(short*)(digit_pairs 2*pos); 
       c-=2;
    }
    while(val>0)
    {
        *c--='0'   (val % 10);
        val /= 10;
    }
    return s;
}

std::string& itostr(unsigned val, std::string& s)
{
    if(val==0)
    {
        s="0";
        return s;
    }

    int size;
    if(val>=10000)
    {
        if(val>=10000000)
        {
            if(val>=1000000000)
                size=10;
            else if(val>=100000000)
                size=9;
            else 
                size=8;
        }
        else
        {
            if(val>=1000000)
                size=7;
            else if(val>=100000)
                size=6;
            else
                size=5;
        }
    }
    else 
    {
        if(val>=100)
        {
            if(val>=1000)
                size=4;
            else
                size=3;
        }
        else
        {
            if(val>=10)
                size=2;
            else
                size=1;
        }
    }

    s.resize(size);
    char* c = &s[size-1];
    while(val>=100)
    {
       int pos = val % 100;
       val /= 100;
       *(short*)(c-1)=*(short*)(digit_pairs 2*pos); 
       c-=2;
    }
    while(val>0)
    {
        *c--='0'   (val % 10);
        val /= 10;
    }
    return s;
}

Bu izin vermemek bellek erişir bu durumda *(short*) ile ilk atama tarafsız bir segfault neden olur () tarafsız sistemler üzerinde patlayacak, ama çok güzel hizmetinde.

Bir şey std::string kullanımını en aza indirmek için. (İronik, biliyorum.) Örneğin, Visual Studio, en std yöntemleri aramalar::dize derleyici seçenekleri /Ob2 belirtmek bile inlined değil. Bu yüzden bile bir şey gibi önemsiz bir çağrı std::string::clear(), beklediğiniz için çok hızlı, alabileceği 100 clockticks bağlantı CRT olarak bir statik kütüphane kadar 300 clockticks bağlantı olarak DLL.

Aynı sebepten dolayı, başvurusu ile dönen bir ödev, bir yapıcı ve yıkıcı önler, çünkü daha iyidir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • AmazonWireless

    AmazonWirele

    8 EYLÜL 2010
  • Marques Brownlee

    Marques Brow

    21 Mart 2008
  • Michelle Phan

    Michelle Pha

    18 Temmuz 2006