È meglio usare std :: memcpy () o std :: copy () in termini di prestazioni?


163

È meglio usare memcpycome mostrato di seguito o è meglio usare std::copy()in termini di prestazioni? Perché?

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]);

Si noti che charpuò essere firmato o non firmato, a seconda dell'implementazione. Se il numero di byte può essere> = 128, utilizzare unsigned charper le matrici di byte. (Anche il (int *)cast sarebbe più sicuro (unsigned int *).)
Dan Breslau il

13
Perché non stai usando std::vector<char>? O dal momento che dici bits, std::bitset?
GManNickG,

2
In realtà, potresti spiegarmi cosa (int*) copyMe->bits[0]fa?
user3728501

4
non so perché qualcosa che sembra un tale pasticcio con un contesto vitale così limitato fosse a +81, ma ehi. @utente3728501 la mia ipotesi è che l'inizio del buffer abbia una intdimensione dettata , ma sembra una ricetta per un disastro definito dall'implementazione, come tante altre cose qui.
underscore_d

2
In effetti, quel (int *)cast è solo puro comportamento indefinito, non definito dall'implementazione. Cercare di punire i caratteri tramite un cast viola le rigide regole di aliasing e quindi non è del tutto definito dalla norma. (Inoltre, in C ++ anche se non in C, non è possibile digitare il pun tramite uno dei uniondue.) Praticamente l'unica eccezione è se si sta convertendo in una variante di char*, ma l'indennità non è simmetrica.
underscore_d

Risposte:


207

Ho intenzione di andare contro la saggezza generale qui che std::copyavrà una leggera, quasi impercettibile perdita di prestazioni. Ho appena fatto un test e ho scoperto che era falso: ho notato una differenza di prestazioni. Tuttavia, il vincitore è stato std::copy.

Ho scritto un'implementazione C ++ SHA-2. Nel mio test, ho eseguito l'hashing di 5 stringhe utilizzando tutte e quattro le versioni SHA-2 (224, 256, 384, 512) e ho eseguito il loop 300 volte. Misuro i tempi usando Boost.timer. Quel contatore di 300 cicli è sufficiente per stabilizzare completamente i miei risultati. Ho eseguito il test 5 volte ciascuno, alternando tra la memcpyversione e la std::copyversione. Il mio codice sfrutta l'acquisizione di dati nel maggior numero possibile di blocchi (molte altre implementazioni funzionano con char/ char *, mentre io opero con T/ T *(dove Tè il tipo più grande nell'implementazione dell'utente che ha un corretto comportamento di overflow), quindi un rapido accesso alla memoria sul i tipi più grandi che posso sono fondamentali per le prestazioni del mio algoritmo. Questi sono i miei risultati:

Tempo (in secondi) per completare l'esecuzione dei test SHA-2

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%

Aumento medio totale della velocità di std :: copia su memcpy: 2,99%

Il mio compilatore è gcc 4.6.3 su Fedora 16 x86_64. Le mie bandiere di ottimizzazione sono -Ofast -march=native -funsafe-loop-optimizations.

Codice per le mie implementazioni SHA-2.

Ho deciso di eseguire un test anche sulla mia implementazione MD5. I risultati erano molto meno stabili, quindi ho deciso di fare 10 corse. Tuttavia, dopo i miei primi tentativi, ho ottenuto risultati che variavano selvaggiamente da una corsa all'altra, quindi suppongo ci fosse una sorta di attività del sistema operativo in corso. Ho deciso di ricominciare.

Stesse impostazioni e flag del compilatore. Esiste una sola versione di MD5, ed è più veloce di SHA-2, quindi ho eseguito 3000 loop su un set simile di 5 stringhe di test.

Questi sono i miei 10 risultati finali:

Tempo (in secondi) per completare l'esecuzione dei test MD5

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%

Diminuzione media totale della velocità di std :: copia su memcpy: 0,11%

Codice per la mia implementazione MD5

Questi risultati suggeriscono che c'è qualche ottimizzazione che std :: copy ha usato nei miei test SHA-2 che std::copynon è stato possibile utilizzare nei miei test MD5. Nei test SHA-2, entrambi gli array sono stati creati nella stessa funzione che ha chiamato std::copy/ memcpy. Nei miei test MD5, uno degli array è stato passato alla funzione come parametro di funzione.

Ho fatto un po 'più di test per vedere cosa avrei potuto fare per std::copyaccelerare di nuovo. La risposta si è rivelata semplice: attiva l'ottimizzazione del tempo di collegamento. Questi sono i miei risultati con LTO attivato (opzione -flto in gcc):

Tempo (in secondi) per completare l'esecuzione dei test MD5 con -flto

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%

Aumento medio totale della velocità di std :: copia su memcpy: 0,72%

In sintesi, non sembra esserci una penalità di prestazione per l'utilizzo std::copy. In effetti, sembra esserci un miglioramento delle prestazioni.

Spiegazione dei risultati

Quindi perché std::copydare un impulso alle prestazioni?

Innanzitutto, non mi aspetto che sia più lento per qualsiasi implementazione, a condizione che l'ottimizzazione dell'inline sia attiva. Tutti i compilatori si allineano in modo aggressivo; è probabilmente l'ottimizzazione più importante perché consente tante altre ottimizzazioni. std::copypuò (e sospetto che tutte le implementazioni del mondo reale lo facciano) rilevare che gli argomenti sono banalmente copiabili e che la memoria è disposta in sequenza. Ciò significa che nel peggiore dei casi, quando memcpyè legale, non std::copydovrebbe andare peggio. L'implementazione banale di std::copyquel difensore memcpydovrebbe soddisfare i criteri del compilatore di "sempre in linea con questo quando si ottimizza per velocità o dimensioni".

Tuttavia, std::copyconserva anche maggiori informazioni. Quando si chiama std::copy, la funzione mantiene intatti i tipi. memcpyopera su void *, che scarta quasi tutte le informazioni utili. Ad esempio, se passo in un array di std::uint64_t, il compilatore o l'implementatore di librerie potrebbero essere in grado di trarre vantaggio dall'allineamento a 64 bit std::copy, ma potrebbe essere più difficile farlo con memcpy. Molte implementazioni di algoritmi come questo funzionano lavorando prima sulla parte non allineata all'inizio dell'intervallo, quindi sulla parte allineata, quindi sulla parte non allineata alla fine. Se è garantito l'allineamento, il codice diventa più semplice e veloce e più facile da correggere per il predittore di diramazione nel processore.

Ottimizzazione prematura?

std::copyè in una posizione interessante. Mi aspetto che non sia mai più lento memcpye talvolta più veloce con qualsiasi moderno compilatore di ottimizzazione. Inoltre, tutto ciò che puoi memcpy, puoi std::copy. memcpynon consente alcuna sovrapposizione nei buffer, mentre i std::copysupporti si sovrappongono in una direzione (con std::copy_backwardper l'altra direzione di sovrapposizione). memcpyfunziona solo su puntatori, std::copyfunziona su qualsiasi iteratori ( std::map, std::vector, std::deque, o il mio tipo personalizzato). In altre parole, dovresti usare solo std::copyquando hai bisogno di copiare blocchi di dati in giro.


35
Voglio sottolineare che ciò non significa che std::copysia il 2,99% o lo 0,72% o il -0,11% più veloce di memcpy, questi tempi sono per l'esecuzione dell'intero programma. Tuttavia, in genere ritengo che i benchmark nel codice reale siano più utili rispetto ai benchmark nel codice falso. Tutto il mio programma ha avuto quel cambiamento nella velocità di esecuzione. Gli effetti reali dei soli due schemi di copia avranno differenze maggiori rispetto a quanto mostrato qui se presi in isolamento, ma ciò dimostra che possono avere differenze misurabili nel codice reale.
David Stone,

2
Voglio essere in disaccordo con i tuoi risultati, ma i risultati sono risultati: /. Comunque una domanda (so che è stata tanto tempo fa e non ricordi la ricerca, quindi commenta come pensi), probabilmente non hai esaminato il codice assembly;
ST3,

2
A mio avviso memcpye std::copyha diverse implementazioni, quindi in alcuni casi il compilatore ottimizza il codice circostante e il codice di copia della memoria effettiva come un pezzo di codice integrale. In altre parole a volte uno è meglio di un altro e persino in altre parole, decidere quale utilizzare è un'ottimizzazione prematura o addirittura stupida, perché in ogni situazione devi fare nuove ricerche e, per di più, i programmi vengono solitamente sviluppati, quindi dopo alcuni piccoli cambiamenti del vantaggio della funzione rispetto ad altri potrebbero andare persi.
ST3,

3
@ ST3: Immagino che nel peggiore dei casi, std::copyè una funzione inline banale che chiama solo memcpyquando è legale. L'allineamento di base eliminerebbe qualsiasi differenza di prestazione negativa. Aggiornerò il post con una spiegazione del perché std :: copy potrebbe essere più veloce.
David Stone,

7
Analisi molto istruttiva. Ri Riduzione media totale della velocità di std :: copy over memcpy: 0,11% , mentre il numero è corretto, i risultati non sono statisticamente significativi. Un intervallo di confidenza al 95% per la differenza nelle medie è (-0,013 s, 0,025), che include zero. Come hai sottolineato, c'erano variazioni rispetto ad altre fonti e con i tuoi dati, probabilmente diresti che le prestazioni sono le stesse. Per riferimento, gli altri due risultati sono statisticamente significativi: le probabilità che tu veda una differenza in tempi così estremi per caso sono circa 1 su 100 milioni (primo) e 1 su 20.000 (ultimo).
TooTone

78

Tutti i compilatori che conosco sostituiranno un semplice std::copycon un memcpyquando è appropriato, o ancora meglio, vettorializzare la copia in modo che sia ancora più veloce di un memcpy.

In ogni caso: profilo e scopri te stesso. Compilatori diversi faranno cose diverse, ed è del tutto possibile che non faccia esattamente quello che chiedi.

Vedi questa presentazione sulle ottimizzazioni del compilatore (pdf).

Ecco cosa fa GCC per un semplice std::copytipo di POD.

#include <algorithm>

struct foo
{
  int x, y;    
};

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

Ecco lo smontaggio (con solo -Oottimizzazione), che mostra la chiamata a 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

Se si cambia la firma della funzione in

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

quindi memmovediventa memcpyun leggero miglioramento delle prestazioni. Si noti che esso memcpystesso sarà fortemente vettorializzato.


1
Come posso fare la profilazione. Quale strumento usare (in Windows e Linux)?
user576670

5
@Konrad, hai ragione. Ma memmovenon dovrebbe essere più veloce, piuttosto dovrebbe essere più lento perché deve tenere conto della possibilità che i due intervalli di dati si sovrappongano. Penso che std::copypermetta la sovrapposizione di dati, e quindi deve chiamare memmove.
Charles Salvia,

2
@Konrad: se memmove fosse sempre più veloce di memcpy, memcpy chiamerebbe memmove. Ciò a cui std :: copy potrebbe effettivamente essere inviato (se non altro) è definito dall'implementazione, quindi non è utile menzionare dettagli senza menzionare l'implementazione.
Fred Nurk,

1
Sebbene, un semplice programma per riprodurre questo comportamento, compilato con -O3 sotto GCC mi mostri a memcpy. Mi porta a credere che GCC controlli se ci sono sovrapposizioni di memoria.
jweyrich,

1
@Konrad: lo standard std::copyconsente la sovrapposizione in una direzione ma non nell'altra. L'inizio dell'output non può trovarsi all'interno dell'intervallo di input, ma l'inizio dell'ingresso può trovarsi all'interno dell'intervallo di output. Questo è un po 'strano, perché è definito l'ordine delle assegnazioni e una chiamata potrebbe essere UB anche se è definito l'effetto di tali assegnazioni, in quell'ordine. Ma suppongo che la restrizione consenta l'ottimizzazione della vettorializzazione.
Steve Jessop,

24

Utilizzare sempre std::copyperché memcpyè limitato solo alle strutture POD di tipo C e il compilatore probabilmente sostituirà le chiamate std::copycon memcpyse le destinazioni sono in realtà POD.

Inoltre, std::copypuò essere utilizzato con molti tipi di iteratori, non solo con puntatori. std::copyè più flessibile senza perdita di prestazioni ed è il chiaro vincitore.


Perché dovresti voler copiare attorno agli iteratori?
Atmocreations

3
Non stai copiando gli iteratori, ma piuttosto l'intervallo definito da due iteratori. Ad esempio, std::copy(container.begin(), container.end(), destination);copierà il contenuto di container(tutto tra begine end) nel buffer indicato da destination. std::copynon richiede shenanigans come &*container.begin()o &container.back() + 1.
David Stone,

16

In teoria, memcpypotrebbe avere un vantaggio prestazionale leggero , impercettibile , infinitesimale , solo perché non ha gli stessi requisiti di std::copy. Dalla pagina man di memcpy:

Per evitare overflow, la dimensione delle matrici indicata dai parametri di destinazione e sorgente deve essere almeno num byte e non deve sovrapporsi (per i blocchi di memoria sovrapposti, memmove è un approccio più sicuro).

In altre parole, memcpypuò ignorare la possibilità di sovrapporre i dati. (Il passaggio di matrici sovrapposte a memcpyè un comportamento indefinito.) Pertanto memcpynon è necessario verificare esplicitamente questa condizione, mentre std::copypuò essere utilizzato purché il OutputIteratorparametro non sia compreso nell'intervallo di origine. Si noti che ciò non equivale a dire che l'intervallo di origine e l'intervallo di destinazione non possono sovrapporsi.

Quindi, poiché std::copyha requisiti leggermente diversi, in teoria dovrebbe essere leggermente (con un'enfasi estrema su leggermente ) più lento, poiché probabilmente controllerà la sovrapposizione di array C, oppure delegherà la copia di array C memmove, che deve eseguire il dai un'occhiata. Ma in pratica, tu (e la maggior parte dei profiler) probabilmente non noterai nemmeno alcuna differenza.

Naturalmente, se non lavori con i POD , non puoimemcpy comunque utilizzarli .


7
Questo è vero per std::copy<char>. Ma std::copy<int>può presumere che i suoi input siano int-allineati. Ciò farà una differenza molto più grande, perché influisce su ogni elemento. La sovrapposizione è un controllo una tantum.
MSalter

2
@MSalters, vero, ma la maggior parte delle implementazioni di memcpycui ho visto controlla l'assetto e cerca di copiare parole anziché byte per byte.
Charles Salvia,

1
std :: copy () può ignorare anche la memoria sovrapposta. Se si desidera supportare la memoria sovrapposta, è necessario scrivere la logica per chiamare std :: reverse_copy () nelle situazioni appropriate.
Cygon,

2
C'è un argomento opposto che può essere fatto: quando si passa attraverso l' memcpyinterfaccia perde le informazioni di allineamento. Quindi, memcpydeve eseguire controlli di allineamento in fase di esecuzione per gestire inizi e fine non allineati. Tali assegni possono essere economici ma non sono gratuiti. Considerando che std::copypuò evitare questi controlli e vettorializzare. Inoltre, il compilatore può dimostrare che gli array di origine e di destinazione non si sovrappongono e vettorializzano nuovamente senza che l'utente debba scegliere tra memcpye memmove.
Maxim Egorushkin,

11

La mia regola è semplice. Se stai usando C ++ preferisci le librerie C ++ e non C :)


40
Il C ++ è stato progettato esplicitamente per consentire l'uso delle librerie C. Questo non è stato un incidente. Spesso è meglio usare std :: copy che memcpy in C ++, ma questo non ha nulla a che fare con quale sia C, e quel tipo di argomento è di solito l'approccio sbagliato.
Fred Nurk,

2
@FredNurk Di solito si desidera evitare un'area debole di C in cui C ++ offre un'alternativa più sicura.
Fil 1970,

@ Phil1970 Non sono sicuro che C ++ sia molto più sicuro in questo caso. Dobbiamo ancora passare iteratori validi che non invasa, ecc ho immagino di essere in grado di utilizzare std::end(c_arr)al posto di c_arr + i_hope_this_is_the_right_number_of elementsè più sicuro? e forse ancora più importante, più chiaro. E questo sarebbe il punto che sottolineo in questo caso specifico: std::copy()è più idiomatico, più mantenibile se i tipi di iteratori cambiano in seguito, porta a una sintassi più chiara, ecc.
underscore_d

1
@underscore_d std::copyè più sicuro perché copia correttamente i dati passati nel caso in cui non siano di tipo POD. memcpycopierà felicemente un std::stringoggetto in una nuova rappresentazione byte per byte.
Jens,

3

Solo un'aggiunta minore: la differenza di velocità tra memcpy()e std::copy()può variare abbastanza a seconda che le ottimizzazioni siano abilitate o disabilitate. Con g ++ 6.2.0 e senza ottimizzazioni memcpy()vince chiaramente:

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

Quando le ottimizzazioni sono abilitate ( -O3), tutto sembra più o meno lo stesso:

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

Più grande è l'array, meno evidente si ottiene l'effetto, ma anche a N=1000 memcpy()è circa due volte più veloce quando le ottimizzazioni non sono abilitate.

Codice sorgente (richiede Google Benchmark):

#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
Misurare le prestazioni con le ottimizzazioni disabilitate è ... beh ... praticamente inutile ... Se sei interessato alle prestazioni, non le compilerai senza ottimizzazioni.
Bolov,

3
@bolov Non sempre. In alcuni casi è importante avere un programma relativamente veloce sotto debug.
Ghianda

2

Se hai davvero bisogno delle massime prestazioni di copiatura (cosa che potresti non fare), non utilizzarle .

C'è molto che si può fare per ottimizzare la copia della memoria - ancora di più se si è disposti a utilizzare più thread / core per questo. Vedi, ad esempio:

Cosa manca / non ottimale in questa implementazione memcpy?

sia la domanda che alcune risposte hanno suggerito implementazioni o collegamenti a implementazioni.


4
modalità pedante: con il solito avvertimento che " non utilizzare nessuno dei due " significa se hai dimostrato di avere una situazione / requisito altamente specifici per i quali nessuna delle funzioni standard fornite dalla tua implementazione è abbastanza veloce ; in caso contrario, la mia solita preoccupazione è che le persone che non hanno dimostrato di essere distratte dall'ottimizzazione prematura del codice di copia invece delle parti solitamente più utili del loro programma.
underscore_d

-2

La profilatura mostra questa affermazione: std::copy()è sempre più veloce memcpy()o più veloce è falso.

Il mio sistema:

HP-Compaq-dx7500-Microtower 3.13.0-24-generic # 47-Ubuntu SMP ven 2 maggio 23 23:00:00 UTC 2014 x86_64 x86_64 x86_64 GNU / Linux.

gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

Il codice (lingua: 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

profilo memcpy (): principale: 21: ora: 1422969084: 04859 trascorso: 2650 us
std :: copia () profilo: principale: 27: ora: 1422969084: 04862 trascorso: 2745 us
memcpy () trascorso 44 s std :: copy ( ) trascorsi 45 secondi

g ++ -O3 -o test_stdcopy test_stdcopy.cpp

profilo memcpy (): principale: 21: ora: 1422969601: 04939 trascorso: 2385 us
std :: copy () profilo: principale: 28: ora: 1422969601: 04941 trascorso: 2690 us
memcpy () trascorso 27 s std :: copy ( ) trascorsi 43 secondi

Red Alert ha sottolineato che il codice utilizza memcpy da array a array e std :: copy da array a vettoriale. Questo potrebbe essere un motivo per memcpy più veloce.

Dal momento che c'è

v.reserve (sizeof (arr1));

non ci devono essere differenze nella copia in formato vettoriale o array.

Il codice è stato risolto per utilizzare l'array per entrambi i casi. memcpy ancora più veloce:

{
    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
sbagliato, la tua profilazione mostra che la copia in un array è più veloce della copia in un vettore. Fuori tema.
Avviso rosso

Potrei sbagliarmi, ma nel tuo esempio corretto, con memcpy, non stai copiando arr2 in arr1, mentre con std :: copy stai copiando arr1 in arr2? ... Quello che potresti fare è fare più, alternando esperimenti (una volta un batch di memcpy, una volta un batch di std :: copy, poi di nuovo con memcopy, ecc., più volte). Quindi, userei clock () invece di time (), perché chissà cosa potrebbe fare il tuo PC oltre a quel programma. Solo i miei due centesimi, però ... :-)
paercebal

7
Quindi, passare std::copyda un vettore a un array in qualche modo ha memcpyrichiesto quasi il doppio del tempo? Questi dati sono altamente sospetti. Ho compilato il tuo codice usando gcc con -O3 e l'assembly generato è lo stesso per entrambi i loop. Quindi qualsiasi differenza nel tempo che osservi sulla tua macchina è solo casuale.
Red Alert,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.