Performans açısından std :: memcpy () veya std :: copy () kullanmak daha mı iyi?


163

memcpyAşağıda gösterildiği gibi kullanmak daha iyi mi yoksa std::copy()performans açısından kullanmak daha mı iyi ? Neden?

char *bits = NULL;
...

bits = new (std::nothrow) char[((int *) copyMe->bits)[0]];
if (bits == NULL)
{
    cout << "ERROR Not enough memory.\n";
    exit(1);
}

memcpy (bits, copyMe->bits, ((int *) copyMe->bits)[0]);

charUygulamaya bağlı olarak imzalı veya imzasız olabileceğini unutmayın . Bayt sayısı> = 128 ise, unsigned charbayt dizileriniz için kullanın . ( (int *)Oyuncular da daha güvenli olurdu (unsigned int *).)
Dan Breslau

13
Neden kullanmıyorsun std::vector<char>? Yoksa söylemek beri bits, std::bitset?
GManNickG

2
Aslında, bana ne yaptığını açıklar (int*) copyMe->bits[0]mısınız?
user3728501

4
Çok az hayati bağlamda böyle bir karmaşa gibi görünen bir şeyin neden +81'de olduğundan emin değilim, ama hey. @ user3728501 Tahminime göre arabellek başlangıcı intboyutunu dikte ediyor, ama buradaki pek çok şey gibi uygulama tanımlı felaket için bir reçete gibi görünüyor.
underscore_d

2
Aslında, bu (int *)kadro, uygulama tanımlı değil, yalnızca tanımsız bir davranıştır. Bir oyuncu kadrosu aracılığıyla tip-kurnaz yapmaya çalışmak, sıkı takma kurallarını ihlal eder ve bu nedenle Standart tarafından tamamen tanımlanmamıştır. (Aynı zamanda, Cı olmasa da, C ++, bir ile-kelime oyunu tip olamaz unionya.) Dönüştürerek eğer hemen hemen tek istisnası için bir varyantında char*, ama karşılık simetrik değildir.
underscore_d

Yanıtlar:


207

Burada, std::copyhafif, neredeyse algılanamayan bir performans kaybına sahip olacak genel bilgeliğe karşı çıkacağım. Sadece bir test yaptım ve yanlış olduğunu gördüm: Bir performans farkı fark ettim. Ancak kazanan oldu std::copy.

Bir C ++ SHA-2 uygulaması yazdım. Testimde, dört SHA-2 sürümünü (224, 256, 384, 512) kullanarak 5 dize hash alıyorum ve 300 kez döngü yapıyorum. Boost.timer kullanarak zamanı ölçüyorum. Bu 300 loop sayacı sonuçlarımı tamamen stabilize etmek için yeterli. Testi, memcpysürüm ve sürüm arasında dönüşümlü olarak 5 kez çalıştırdım std::copy. Kodum, verileri olabildiğince büyük yığınlardan yakalama avantajından yararlanır (diğer birçok uygulama char/ ile çalışır char *, oysa T/ ile çalışırım T *( Tkullanıcının uygulamasında doğru taşma davranışına sahip en büyük türdür), bu nedenle hızlı bellek erişimi yapabileceğim en büyük tipler algoritmamın performansında çok önemli.

SHA-2 testlerinin tamamlanma süresi (saniye olarak)

std::copy   memcpy  % increase
6.11        6.29    2.86%
6.09        6.28    3.03%
6.10        6.29    3.02%
6.08        6.27    3.03%
6.08        6.27    3.03%

Standart hızdaki ortalama ortalama artış :: memcpy üzerinden kopya:% 2.99

Derleyicim Fedora 16 x86_64 üzerinde gcc 4.6.3. Optimizasyon bayraklarım -Ofast -march=native -funsafe-loop-optimizations.

SHA-2 uygulamalarım için kod.

MD5 uygulamam üzerinde de bir test yapmaya karar verdim. Sonuçlar çok daha az kararlıydı, bu yüzden 10 koşu yapmaya karar verdim. Ancak, ilk birkaç denememden sonra, bir koşudan diğerine çılgınca değişen sonuçlar aldım, bu yüzden bir tür işletim sistemi faaliyeti olduğunu tahmin ediyorum. Başlamaya karar verdim.

Aynı derleyici ayarları ve bayrakları. MD5'in yalnızca bir sürümü var ve SHA-2'den daha hızlı, bu yüzden benzer 5 test dizisi üzerinde 3000 döngü yaptım.

Bunlar benim son 10 sonuç:

MD5 testlerinin tamamlanma süresi (saniye olarak)

std::copy   memcpy      % difference
5.52        5.56        +0.72%
5.56        5.55        -0.18%
5.57        5.53        -0.72%
5.57        5.52        -0.91%
5.56        5.57        +0.18%
5.56        5.57        +0.18%
5.56        5.53        -0.54%
5.53        5.57        +0.72%
5.59        5.57        -0.36%
5.57        5.56        -0.18%

Standart hızdaki ortalama ortalama azalma :: memcpy üzerinden kopyalama:% 0.11

MD5 uygulamam için kod

Bu sonuçlar, std::copyMD5 testlerimde kullanamadığım SHA-2 testlerimde kullanılan std :: copy'ın bazı optimizasyonları olduğunu göstermektedir . SHA-2 testlerinde, her iki dizi std::copy/ adında aynı işlevle oluşturuldu memcpy. MD5 testlerimde dizilerden biri işleve bir işlev parametresi olarak iletildi.

std::copyTekrar hızlandırmak için neler yapabileceğimi görmek için biraz daha test yaptım . Yanıtın basit olduğu ortaya çıktı: bağlantı süresi optimizasyonunu açın. Bunlar LTO açıkken sonuçlarım (gcc'de -flto seçeneği):

-Flto ile MD5 testlerinin tamamlanma süresi (saniye olarak)

std::copy   memcpy      % difference
5.54        5.57        +0.54%
5.50        5.53        +0.54%
5.54        5.58        +0.72%
5.50        5.57        +1.26%
5.54        5.58        +0.72%
5.54        5.57        +0.54%
5.54        5.56        +0.36%
5.54        5.58        +0.72%
5.51        5.58        +1.25%
5.54        5.57        +0.54%

Standart hızdaki ortalama ortalama artış :: Memcpy üzerinden kopyalama:% 0,72

Özetle, kullanım için bir performans cezası yok gibi görünüyor std::copy. Aslında, bir performans kazancı var gibi görünüyor.

Sonuçların açıklaması

Öyleyse neden std::copyperformans artışı sağlayabilir ?

İlk olarak, satır içi optimizasyon açık olduğu sürece herhangi bir uygulama için daha yavaş olmasını beklemezdim. Tüm derleyiciler agresif olarak satır içi; diğer birçok optimizasyonu mümkün kıldığı için muhtemelen en önemli optimizasyondur. std::copyargümanların önemsiz şekilde kopyalandığını ve belleğin sırayla düzenlendiğini tespit edebilir (ve tüm gerçek dünya uygulamalarından şüpheleniyorum). Bu, en kötü durumda, memcpyyasal olduğunda , std::copydaha kötü bir performans göstermemesi gerektiği anlamına gelir . Önemsiz uygulama std::copyolduğunu ertelemektedir için memcpy"her zaman satır içi bu hız veya boyut için optimize ederken" tutarındaki derleyici'nın kriterlerini karşılamalıdır.

Ancak, std::copydaha fazla bilgi tutar. Aradığınızda std::copy, işlev türleri sağlam tutar. memcpyçalışır void *hangi silip mevcut neredeyse tüm yararlı bilgiler. Örneğin, bir diziden std::uint64_tgeçersem, derleyici veya kütüphane uygulayıcısı 64 bit hizalamadan yararlanabilir std::copy, ancak bunu yapmak daha zor olabilir memcpy. Bunun gibi birçok algoritma uygulaması önce aralığın başında hizalanmamış kısım, daha sonra hizalanmış kısım, daha sonra sonda hizalanmamış kısım üzerinde çalışarak çalışır. Tümünün hizalanması garanti edilirse, kod daha basit ve daha hızlı hale gelir ve işlemcinizdeki dal öngörücüsünün doğru olması daha kolay hale gelir.

Erken optimizasyon?

std::copyilginç bir konumda. memcpyHerhangi bir modern optimizasyon derleyici ile asla daha yavaş ve bazen daha hızlı olmasını bekliyorum . Üstelik yapabildiğiniz her şeyi memcpyyapabilirsiniz std::copy. memcpytamponlarda herhangi bir üst üste binmeye izin vermezken, std::copydestekler bir yönde üst üste binmeyi destekler ( std::copy_backwarddiğer üst üste binme yönüyle birlikte). memcpyYalnızca, işaretçiler çalışır std::copyherhangi Yineleyicilerin çalışır ( std::map, std::vector, std::deque, veya kendi özel tip). Başka bir deyişle, sadece std::copyveri yığınlarını kopyalamanız gerektiğinde kullanmalısınız .


35
Bunun std::copy% 2.99 veya% 0.72 veya% -0.11 daha hızlı olduğu anlamına gelmediğini vurgulamak istiyorum memcpy, bu süreler tüm programın yürütülmesi içindir. Ancak, genellikle gerçek koddaki ölçütlerin sahte koddaki ölçütlerden daha yararlı olduğunu hissediyorum. Tüm programım yürütme hızında bu değişikliği aldı. Yalnızca iki kopyalama şemasının gerçek etkileri, tek başına alındığında burada gösterilenden daha büyük farklılıklara sahip olacaktır, ancak bu, gerçek kodda ölçülebilir farklılıklara sahip olabileceğini gösterir.
David Stone

2
Bulgularınıza katılmıyorum, ancak sonuçlar sonuç: /. Ancak bir soru (uzun zaman önce olduğunu biliyorum ve araştırma hatırlamıyorum, bu yüzden sadece düşündüğün gibi yorum), muhtemelen montaj kodu bakmadı;
ST3

2
Bence memcpyve std::copyfarklı uygulamaları vardır, bu nedenle bazı durumlarda derleyici çevreleyen kodu ve gerçek bellek kopya kodunu tek bir entegre kod parçası olarak optimize eder. Başka bir deyişle bazen biri diğerinden daha iyidir ve başka bir deyişle, hangisinin kullanılacağına karar vermek erken veya hatta aptal optimizasyondur, çünkü her durumda yeni araştırma yapmak zorundasınız ve dahası, programlar genellikle geliştiriliyor, bazı küçük değişiklikler fonksiyonun diğerlerine göre avantajı kaybolabilir.
ST3

3
@ ST3: En kötü durumda, std::copysadece memcpyyasal olduğunda çağıran önemsiz bir satır içi işlev olduğunu hayal ediyorum . Temel satır içi, herhangi bir negatif performans farkını ortadan kaldıracaktır. Yazıyı, std :: copy'ın neden daha hızlı olabileceğine dair bir açıklama ile güncelleyeceğim.
David Stone

7
Çok bilgilendirici analiz. Re std :: memcpy üzerinden kopyadaki toplam ortalama azalma:% 0.11 , sayı doğru olsa da, sonuçlar istatistiksel olarak anlamlı değildir. Ortalamalardaki fark için% 95 güven aralığı, sıfır içeren (-0.013s, 0.025) 'dir. Diğer kaynaklardan ve verilerinizden farklılıklar olduğuna dikkat çektiğiniz gibi, muhtemelen performansın aynı olduğunu söylerdiniz. Referans olarak, diğer iki sonuç istatistiksel olarak anlamlıdır - bu uç noktadaki şans eseri zamanlarında bir fark görme şansınız 100 milyonda (ilk) yaklaşık 1 ve 20.000'de (son) 1'dir.
2016

78

Bir basit yerini alacak bildiğim derleyiciler std::copybir ile memcpydaha da iyi uygun ya olduğunda, bu yüzden daha hızlı bir daha olacağını kopya vektörize memcpy.

Her durumda: profil oluşturun ve kendinizi bulun. Farklı derleyiciler farklı şeyler yaparlar ve tam olarak ne istersen yapmazlar.

Derleyici optimizasyonları hakkındaki bu sunuma bakınız (pdf).

İşte PCC'nin basit std::copybir POD tipi için yaptığı şey .

#include <algorithm>

struct foo
{
  int x, y;    
};

void bar(foo* a, foo* b, size_t n)
{
  std::copy(a, a + n, b);
}

İşte -Oçağrıyı gösteren sökme (sadece optimizasyon ile) memmove:

bar(foo*, foo*, unsigned long):
    salq    $3, %rdx
    sarq    $3, %rdx
    testq   %rdx, %rdx
    je  .L5
    subq    $8, %rsp
    movq    %rsi, %rax
    salq    $3, %rdx
    movq    %rdi, %rsi
    movq    %rax, %rdi
    call    memmove
    addq    $8, %rsp
.L5:
    rep
    ret

İşlev imzasını

void bar(foo* __restrict a, foo* __restrict b, size_t n)

sonra hafif bir performans artışı için bir memmoveolur memcpy. O Not memcpykendisi ağır vektörleştirilmiş edilecektir.


1
Nasıl profil oluşturabilirim? Hangi araç kullanılacak (Windows ve Linux'ta)?
user576670

5
@Konrad, haklısın. Ancak memmovedaha hızlı olmamalı - daha ziyade daha yavaş olmalı, çünkü iki veri aralığının çakışması olasılığını hesaba katmalıdır. Bence std::copyörtüşen veriye izin veriyor ve bu yüzden çağırmak zorunda memmove.
Charles Salvia

2
@Konrad: Memmove her zaman memcpy'dan daha hızlı olsaydı, memcpy memmove'u çağırırdı. Std :: copy uygulamasının gerçekte neyi gönderebileceği (eğer varsa) uygulama tanımlıdır, bu nedenle uygulamadan bahsetmeden ayrıntılardan bahsetmek yararlı değildir.
Fred Nurk

1
Rağmen, bu davranışı yeniden üretmek için basit bir program, GCC altında -O3 ile derlenmiş bana bir gösterir memcpy. Beni GCC'nin bellek çakışması olup olmadığını kontrol ettiğine inanıyorum.
jweyrich

1
@Konrad: standart std::copybir yönde çakışmaya izin verir, diğerinde değil. Çıktının başlangıcı giriş aralığının içinde olamaz, ancak girdinin başlangıcının çıkış aralığı içinde kalmasına izin verilir. Bu biraz gariptir, çünkü atamaların sırası tanımlanır ve bu atamaların etkisi, bu sırayla tanımlanmış olsa bile bir çağrı UB olabilir. Ancak kısıtlamanın vektörizasyon optimizasyonlarına izin verdiğini düşünüyorum.
Steve Jessop

24

Daima kullanmak std::copyçünkü memcpysadece C tarzı POD yapılara sınırlıdır ve derleyici olasılıkla çağrı yerini alacak std::copyolan memcpyhedefler aslında POD ise.

Ayrıca, std::copyyalnızca işaretçilerle değil, birçok yineleyici türüyle kullanılabilir. std::copyhiçbir performans kaybı olmadan daha esnektir ve açık kazanır.


Neden yineleyicilerin etrafına kopyalamak istersiniz?
Atmocreations

3
Yineleyicileri değil, iki yineleyici tarafından tanımlanan aralığı kopyalıyorsunuz. Örneğin std::copy(container.begin(), container.end(), destination);, container( beginve arasındaki her şeyi end) ile gösterilen ara belleğe kopyalar destination. veya std::copygibi maskaralık gerektirmez . &*container.begin()&container.back() + 1
David Stone

16

Teoride, ancak aynı gerekliliklere sahip olmadığı memcpyiçin hafif , algılanamayan , sonsuz bir performans avantajına sahip olabilir std::copy. Man sayfasından memcpy:

Taşmaları önlemek için, hem hedef hem de kaynak parametreleri tarafından işaretlenen dizilerin boyutu en az sayı bayt olmalı ve üst üste binmemelidir (çakışan bellek blokları için, memmove daha güvenli bir yaklaşımdır).

Başka bir deyişle, memcpyverilerin çakışması olasılığını göz ardı edebilir. (Üst üste binen dizileri geçmek memcpytanımsız bir davranıştır.) Bu nedenle memcpybu durumu açıkça kontrol etmek gerekmez, ancak parametre kaynak aralığında olmadığı std::copysürece kullanılabilir OutputIterator. Bunun, kaynak aralığının ve hedef aralığının çakışamayacağını söylemekle aynı olmadığını unutmayın .

Yani beri std::copyolması gerektiği teoride, biraz farklı gereksinimleri vardır hafifçe (üzerinde aşırı bir vurgu ile hafifçe muhtemelen C-diziler örtüşen kontrol, ya da başka C-Dizilerin kopyalanmasını temsilci olacağından, daha yavaş) memmovegerçekleştirmek gerekiyor Kontrol. Ancak pratikte, siz (ve çoğu profil sahibi) muhtemelen herhangi bir fark bile tespit etmeyeceksiniz.

Birlikte çalıştığınız değilseniz Tabii ki, PODs , sen olamaz kullanmak memcpyzaten.


7
Bu doğrudur std::copy<char>. Ancak std::copy<int>girdilerinin int-hizalı olduğunu varsayabiliriz. Bu çok daha büyük bir fark yaratacaktır, çünkü her unsuru etkiler. Çakışma bir kerelik bir kontroldür.
MSalters

2
@MSalters, doğru, ama çoğu uygulama memcpyhizalama kontrol bayt bayt yerine sözcükleri kopyalamak için denedim.
Charles Salvia

1
std :: copy () çakışan belleği de göz ardı edebilir. Çakışan belleği desteklemek istiyorsanız, uygun durumlarda std :: reverse_copy () öğesini çağırmak için mantığı kendiniz yazmanız gerekir.
Cygon

2
Yapılması gereken ters bir argüman var: memcpyarayüzden geçerken hizalama bilgilerini kaybeder. Bu nedenle, memcpyhizalanmamış başlangıç ​​ve bitişleri işlemek için çalışma zamanında hizalama kontrolleri yapmak zorundadır. Bu kontroller ucuz olabilir ancak ücretsiz değildir. Oysa std::copybu kontrollerden kaçınabilir ve vektörize edebilir. Ayrıca, derleyici, kaynak ve hedef dizilerin örtüşmediğini ve kullanıcı memcpyve arasında seçim yapmak zorunda kalmadan yeniden vektörleşmediğini kanıtlayabilir memmove.
Maxim Egorushkin

11

Kuralım basit. C ++ kullanıyorsanız C ++ değil C ++ kütüphanelerini tercih edin


40
C ++, C kitaplıklarının kullanımına izin vermek için açıkça tasarlanmıştır. Bu bir kaza değildi. Genellikle std :: copy kullanmak C ++ 'da memcpy'den daha iyidir, ancak bunun hangisinin C olduğu ile ilgisi yoktur ve bu tür bir argüman genellikle yanlış yaklaşımdır.
Fred Nurk

2
@FredNurk Genellikle C ++ 'nın daha güvenli bir alternatif sağladığı zayıf C alanından kaçınmak istersiniz.
Phil1970

@ Phil1970 Bu durumda C ++ 'ın çok daha güvenli olduğundan emin değilim. Hâlâ aşılmayan geçerli yineleyicileri geçmek zorundayız. Sanırım kullanmak std::end(c_arr)yerine kullanmak c_arr + i_hope_this_is_the_right_number_of elementsdaha güvenli mi? ve belki daha da önemlisi, daha net. Ve bu özel durumda vurguladığım nokta bu olurdu: std::copy()yineleyicilerin türleri daha sonra değişirse, daha açık sözdizimine yol açarsa, daha deyimsel, daha sürdürülebilir.
underscore_d

1
@underscore_d std::copydaha güvenlidir, çünkü POD tipi olmamaları durumunda iletilen verileri doğru bir şekilde kopyalar. memcpybir std::stringnesneyi mutlu bir şekilde yeni bir temsil bayt baytına kopyalar .
Jens

3

Sadece küçük bir ekleme: Optimizasyonların etkin veya devre dışı olmasına bağlı olarak memcpy()ve arasındaki hız farkı std::copy()biraz değişebilir. G ++ 6.2.0 ve optimizasyon olmadan memcpy()açıkça kazanır:

Benchmark             Time           CPU Iterations
---------------------------------------------------
bm_memcpy            17 ns         17 ns   40867738
bm_stdcopy           62 ns         62 ns   11176219
bm_stdcopy_n         72 ns         72 ns    9481749

Optimizasyonlar etkinleştirildiğinde ( -O3), her şey tekrar aynı görünür:

Benchmark             Time           CPU Iterations
---------------------------------------------------
bm_memcpy             3 ns          3 ns  274527617
bm_stdcopy            3 ns          3 ns  272663990
bm_stdcopy_n          3 ns          3 ns  274732792

Dizi ne kadar büyük olursa, efekt o kadar az fark edilir, ancak en N=1000 memcpy()iyisi, optimizasyonlar etkinleştirilmediğinde yaklaşık iki kat daha hızlıdır.

Kaynak kodu (Google Benchmark gerektirir):

#include <string.h>
#include <algorithm>
#include <vector>
#include <benchmark/benchmark.h>

constexpr int N = 10;

void bm_memcpy(benchmark::State& state)
{
  std::vector<int> a(N);
  std::vector<int> r(N);

  while (state.KeepRunning())
  {
    memcpy(r.data(), a.data(), N * sizeof(int));
  }
}

void bm_stdcopy(benchmark::State& state)
{
  std::vector<int> a(N);
  std::vector<int> r(N);

  while (state.KeepRunning())
  {
    std::copy(a.begin(), a.end(), r.begin());
  }
}

void bm_stdcopy_n(benchmark::State& state)
{
  std::vector<int> a(N);
  std::vector<int> r(N);

  while (state.KeepRunning())
  {
    std::copy_n(a.begin(), N, r.begin());
  }
}

BENCHMARK(bm_memcpy);
BENCHMARK(bm_stdcopy);
BENCHMARK(bm_stdcopy_n);

BENCHMARK_MAIN()

/* EOF */

18
Devre dışı bırakılan optimizasyonlarla performansı ölçmek ... iyi ... neredeyse anlamsız ... Performansla ilgileniyorsanız, optimizasyon olmadan derlemeyeceksiniz.
16:32 bolov

3
@bolov Her zaman değil. Hata ayıklama altında nispeten hızlı bir programın olması bazı durumlarda önemlidir.
Acorn

2

Gerçekten maksimum kopyalama performansına ihtiyacınız varsa (ki olmayabilir de), hiçbirini kullanmayın .

Bir var çok optimize hafıza kopyalama için yapılabilecek - hatta daha bunun için sen istekli birden konuları kullanmak eğer / çekirdekler. Bkz. Örneğin:

Bu memcpy uygulamasında eksik / alt optimal olan nedir?

hem soru hem de cevapların bazıları önerilen uygulamaları veya uygulamalara bağlantıları önerdi.


4
bilgiç modu: "O zamanki ikaz ile ikisi de kullanım aracı" Eğer yeterince hızlı olduğunu uygulamanızda tarafından sağlanan hangi ne Standart fonksiyonu için son derece spesifik durum / gereksinimi olduğunu kanıtlamıştır eğer ; aksi takdirde, her zamanki kaygım, programlarının genellikle daha yararlı kısımları yerine kopyalama kodunu erken optimize etmede kanıtlanamayan insanlar.
underscore_d

-2

Profil oluşturma şu ifadeyi gösterir: std::copy()her zaman olduğu kadar hızlı memcpy()veya daha hızlı yanlıştır.

Sistemim:

HP-Compaq-dx7500-Küçük Kasa 3.13.0-24-jenerik # 47-Ubuntu SMP Cum 2 Mayıs 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU / Linux.

gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

Kod (dil: c ++):

    const uint32_t arr_size = (1080 * 720 * 3); //HD image in rgb24
    const uint32_t iterations = 100000;
    uint8_t arr1[arr_size];
    uint8_t arr2[arr_size];
    std::vector<uint8_t> v;

    main(){
        {
            DPROFILE;
            memcpy(arr1, arr2, sizeof(arr1));
            printf("memcpy()\n");
        }

        v.reserve(sizeof(arr1));
        {
            DPROFILE;
            std::copy(arr1, arr1 + sizeof(arr1), v.begin());
            printf("std::copy()\n");
        }

        {
            time_t t = time(NULL);
            for(uint32_t i = 0; i < iterations; ++i)
                memcpy(arr1, arr2, sizeof(arr1));
            printf("memcpy()    elapsed %d s\n", time(NULL) - t);
        }

        {
            time_t t = time(NULL);
            for(uint32_t i = 0; i < iterations; ++i)
                std::copy(arr1, arr1 + sizeof(arr1), v.begin());
            printf("std::copy() elapsed %d s\n", time(NULL) - t);
        }
    }

g ++ -O0 -o test_stdcopy test_stdcopy.cpp

memcpy () profili: main: 21: now: 1422969084: 04859 geçen: 2650 us
std :: copy () profil: main: 27: now: 1422969084: 04862 geçen: 2745 us
memcpy () geçen 44 s std :: copy ( ) geçen 45 s

g ++ -O3 -o test_stdcopy test_stdcopy.cpp

memcpy () profili: main: 21: now: 1422969601: 04939 geçen: 2385 us
std :: copy () profil: main: 28: now: 1422969601: 04941 geçen: 2690 us
memcpy () geçen 27 s std :: copy ( ) geçen süre 43 s

Red Alert, kodun diziden diziye memcpy kullandığını ve diziden vektöre std :: copy olduğunu belirtti. Bu coud daha hızlı memcpy için bir sebep olabilir.

Den beri

v.reserve (sizeof (arr1));

vektör veya diziye kopyalamada hiçbir fark olmayacaktır.

Kod, her iki durumda da dizi kullanmak üzere sabitlenmiştir. memcpy hala daha hızlı:

{
    time_t t = time(NULL);
    for(uint32_t i = 0; i < iterations; ++i)
        memcpy(arr1, arr2, sizeof(arr1));
    printf("memcpy()    elapsed %ld s\n", time(NULL) - t);
}

{
    time_t t = time(NULL);
    for(uint32_t i = 0; i < iterations; ++i)
        std::copy(arr1, arr1 + sizeof(arr1), arr2);
    printf("std::copy() elapsed %ld s\n", time(NULL) - t);
}

memcpy()    elapsed 44 s
std::copy() elapsed 48 s 

1
yanlış, profil oluşturma, bir diziye kopyalamanın bir vektöre kopyalamaktan daha hızlı olduğunu gösterir. Konu dışı.
Red Alert

Yanlış olabilirim, ancak düzeltilmiş örneğinizde, memcpy ile, arr2'yi arr1'e kopyalamıyor musunuz, std :: copy ile arr1'i arr2'ye kopyalıyorsunuz? ... Yapabileceğiniz şey, çoklu, alternatif yapmaktır deneyler (bir kez memcpy, bir kez std :: copy, sonra tekrar memcopy, vb. ile tekrar tekrar). Sonra, time () yerine clock () kullanırdım, çünkü PC'nizin bu programa ek olarak neler yapabileceğini kim bilebilir? Sadece benim iki sent olsa ... :-)
paercebal

7
Yani, std::copybir vektörden bir diziye geçmek bir şekilde memcpyneredeyse iki kat daha uzun sürüyor mu? Bu veriler oldukça şüphelidir. Kodunuzu -O3 ile gcc kullanarak derledim ve oluşturulan derleme her iki döngü için de aynı. Bu nedenle, makinenizde gözlemlediğiniz zaman farkı yalnızca rastlantısaldır.
Red Alert
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.