Est-il préférable d'utiliser std :: memcpy () ou std :: copy () en termes de performances?

163

Vaut-il mieux utiliser memcpycomme indiqué ci-dessous ou est-il préférable d'utiliser std::copy()en termes de performances? Pourquoi?

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]);
utilisateur576670
la source
Notez qui charpeut être signé ou non signé, selon l'implémentation. Si le nombre d'octets peut être> = 128, utilisez unsigned charpour vos tableaux d'octets. (Le (int *)casting serait aussi plus sûr (unsigned int *).)
Dan Breslau
13
Pourquoi n'utilisez-vous pas std::vector<char>? Ou puisque vous dites bits, std::bitset?
GManNickG
2
En fait, pouvez-vous m'expliquer ce que (int*) copyMe->bits[0]fait?
user3728501
4
Je ne sais pas pourquoi quelque chose qui semble être un tel désordre avec si peu de contexte vital fourni était à +81, mais bon. @ user3728501 Je suppose que le début de la mémoire tampon contient une intdéfinition de sa taille, mais cela semble être une recette pour un désastre défini par l'implémentation, comme tant d'autres choses ici.
underscore_d
2
En fait, ce (int *)cast est juste un comportement indéfini pur, pas défini par l'implémentation. Essayer de faire du poinçonnage de type via une distribution enfreint les règles strictes d'aliasing et est donc totalement indéfini par le Standard. (De plus, en C ++ mais pas en C, vous ne pouvez pas non plus taper un jeu de mots via a union.) La seule exception est si vous convertissez en une variante de char*, mais l'allocation n'est pas symétrique.
underscore_d

Réponses:

207

Je vais aller à l'encontre de la sagesse générale ici qui std::copyentraînera une légère perte de performance presque imperceptible. Je viens de faire un test et j'ai trouvé que c'était faux: j'ai remarqué une différence de performance. Cependant, le gagnant était std::copy.

J'ai écrit une implémentation C ++ SHA-2. Dans mon test, je hache 5 chaînes en utilisant les quatre versions SHA-2 (224, 256, 384, 512) et je boucle 300 fois. Je mesure les temps en utilisant Boost.timer. Ce compteur de 300 boucles suffit à stabiliser complètement mes résultats. J'ai effectué le test 5 fois chacun, en alternant entre la memcpyversion et la std::copyversion. Mon code tire parti de la saisie de données en aussi gros morceaux que possible (de nombreuses autres implémentations fonctionnent avec char/ char *, alors que j'opère avec T/ T *(où Test le plus grand type dans l'implémentation de l'utilisateur qui a un comportement de débordement correct), donc un accès mémoire rapide sur le les plus grands types possibles sont essentiels aux performances de mon algorithme. Voici mes résultats:

Temps (en secondes) pour terminer l'exécution des tests 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%

Augmentation moyenne totale de la vitesse de std :: copy sur memcpy: 2,99%

Mon compilateur est gcc 4.6.3 sur Fedora 16 x86_64. Mes indicateurs d'optimisation sont -Ofast -march=native -funsafe-loop-optimizations.

Code pour mes implémentations SHA-2.

J'ai décidé de tester également mon implémentation MD5. Les résultats étaient beaucoup moins stables, j'ai donc décidé de faire 10 courses. Cependant, après mes premières tentatives, j'ai obtenu des résultats qui variaient énormément d'une exécution à l'autre, donc je suppose qu'il y avait une sorte d'activité du système d'exploitation. J'ai décidé de recommencer.

Mêmes paramètres et indicateurs du compilateur. Il n'y a qu'une seule version de MD5, et c'est plus rapide que SHA-2, j'ai donc fait 3000 boucles sur un ensemble similaire de 5 chaînes de test.

Voici mes 10 derniers résultats:

Temps (en secondes) pour terminer l'exécution des tests 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%

Diminution moyenne totale de la vitesse de std :: copy sur memcpy: 0,11%

Code pour mon implémentation MD5

Ces résultats suggèrent qu'il existe une certaine optimisation que std :: copy utilisée dans mes tests SHA-2 qui std::copyn'a pas pu être utilisée dans mes tests MD5. Dans les tests SHA-2, les deux tableaux ont été créés dans la même fonction qui a appelé std::copy/memcpy . Dans mes tests MD5, l'un des tableaux a été transmis à la fonction en tant que paramètre de fonction.

J'ai fait un peu plus de tests pour voir ce que je pouvais faire pour std::copyaccélérer à nouveau. La réponse s'est avérée simple: activez l'optimisation du temps de liaison. Voici mes résultats avec LTO activé (option -flto dans gcc):

Temps (en secondes) pour terminer l'exécution des tests MD5 avec -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%

Augmentation moyenne totale de la vitesse de std :: copy sur memcpy: 0,72%

En résumé, il ne semble pas y avoir de pénalité de performance pour l'utilisation std::copy. En fait, il semble y avoir un gain de performance.

Explication des résultats

Alors, pourquoi pourrait-il std::copyaugmenter les performances?

Premièrement, je ne m'attendrais pas à ce qu'il soit plus lent pour une implémentation, tant que l'optimisation de l'inlining est activée. Tous les compilateurs en ligne de manière agressive; c'est peut-être l'optimisation la plus importante car elle permet de nombreuses autres optimisations. std::copypeut (et je soupçonne que toutes les implémentations du monde réel le font) détecter que les arguments sont trivialement copiables et que la mémoire est disposée séquentiellement. Cela signifie que dans le pire des cas, quand memcpyc'est légal, std::copyne devrait pas être pire. L'implémentation triviale de std::copyce report memcpydevrait répondre aux critères de votre compilateur de "toujours en ligne lors de l'optimisation de la vitesse ou de la taille".

Cependant, std::copyconserve également plus de ses informations. Lorsque vous appelez std::copy, la fonction conserve les types intacts. memcpyfonctionne void *, ce qui supprime presque toutes les informations utiles. Par exemple, si je passe dans un tableau de std::uint64_t, le compilateur ou l'implémenteur de la bibliothèque peut être en mesure de profiter de l'alignement 64 bits avec std::copy, mais il peut être plus difficile de le faire avec memcpy. De nombreuses implémentations d'algorithmes comme celui-ci fonctionnent en travaillant d'abord sur la partie non alignée au début de la plage, puis sur la partie alignée, puis sur la partie non alignée à la fin. S'il est garanti que tout est aligné, le code devient plus simple et plus rapide, et plus facile pour le prédicteur de branche de votre processeur à être correct.

Optimisation prématurée?

std::copyest dans une position intéressante. Je m'attends à ce qu'il ne soit jamais plus lent memcpyet parfois plus rapide avec n'importe quel compilateur d'optimisation moderne. De plus, tout ce que vous pouvez memcpy, vous le pouvez std::copy. memcpyne permet aucun chevauchement dans les tampons, alors que les std::copysupports se chevauchent dans un sens (avec std::copy_backwardpour l'autre sens de recouvrement). memcpyne fonctionne que sur des pointeurs, std::copyfonctionne sur tous les itérateurs ( std::map, std::vector, std::deque, ou mon propre type personnalisé). En d'autres termes, vous ne devriez l'utiliser que std::copylorsque vous avez besoin de copier des morceaux de données.

David Stone
la source
35
Je tiens à souligner que cela ne signifie pas que std::copyc'est 2,99% ou 0,72% ou -0,11% plus rapide que memcpy, ces temps sont pour tout le programme à exécuter. Cependant, je pense généralement que les benchmarks dans du code réel sont plus utiles que les benchmarks dans du faux code. Tout mon programme a eu ce changement de vitesse d'exécution. Les effets réels des deux schémas de copie seulement auront des différences plus importantes que celles indiquées ici lorsqu'ils sont pris isolément, mais cela montre qu'ils peuvent avoir des différences mesurables dans le code réel.
David Stone
2
Je ne suis pas d'accord avec vos conclusions, mais les résultats sont des résultats: /. Cependant, une question (je sais que c'était il y a longtemps et vous ne vous souvenez pas de la recherche, alors commentez simplement la façon dont vous pensez), vous n'avez probablement pas examiné le code d'assemblage;
ST3
2
À mon avis, memcpyet std::copya différentes implémentations, donc dans certains cas, le compilateur optimise le code environnant et le code de copie de mémoire réel comme un morceau de code intégral. En d'autres termes, parfois l' un est meilleur que l'autre et même en d'autres termes, décider lequel utiliser est une optimisation prématurée ou même stupide, car dans chaque situation, vous devez faire de nouvelles recherches et, de plus, des programmes sont généralement en cours de développement, donc après certains changements mineurs peuvent perdre l'avantage de la fonction sur d'autres.
ST3
3
@ ST3: J'imagine que dans le pire des cas, std::copyc'est une fonction en ligne triviale qui n'appelle que memcpyquand c'est légal. L'inlining de base éliminerait toute différence de performance négative. Je vais mettre à jour le message avec une petite explication de la raison pour laquelle std :: copy pourrait être plus rapide.
David Stone
7
Analyse très informative. Re Diminution moyenne totale de la vitesse de std :: copy par rapport à memcpy: 0,11% , alors que le nombre est correct, les résultats ne sont pas statistiquement significatifs. Un intervalle de confiance à 95% pour la différence des moyennes est (-0,013s, 0,025), qui comprend zéro. Comme vous l'avez souligné, il y avait des variations par rapport à d'autres sources et avec vos données, vous diriez probablement que les performances sont les mêmes. À titre de référence, les deux autres résultats sont statistiquement significatifs - les chances que vous voyiez une différence de temps aussi extrême par hasard sont d'environ 1 sur 100 millions (premier) et 1 sur 20000 (dernier).
TooTone
78

Tous les compilateurs que je connais remplaceront un simple std::copypar un memcpyquand c'est approprié, ou encore mieux, vectoriseront la copie pour qu'elle soit encore plus rapide qu'un memcpy.

Dans tous les cas: profilez et découvrez vous-même. Différents compilateurs feront des choses différentes, et il est fort possible qu'il ne fasse pas exactement ce que vous demandez.

Voir cette présentation sur les optimisations du compilateur (pdf).

Voici ce que fait GCC pour un simple std::copyde type POD.

#include <algorithm>

struct foo
{
  int x, y;    
};

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

Voici le démontage (avec seulement l' -Ooptimisation), montrant l'appel à 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

Si vous modifiez la signature de la fonction en

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

puis le memmovedevient un memcpypour une légère amélioration des performances. Notez que memcpylui - même sera fortement vectorisé.

Peter Alexander
la source
1
Comment puis-je faire du profilage. Quel outil utiliser (sous Windows et Linux)?
user576670
5
@Konrad, vous avez raison. Mais cela memmovene devrait pas être plus rapide, mais plutôt plus lent, car il doit prendre en compte la possibilité que les deux plages de données se chevauchent. Je pense que std::copypermet le chevauchement des données, et donc il faut appeler memmove.
Charles Salvia
2
@Konrad: Si memmove était toujours plus rapide que memcpy, alors memcpy appellerait memmove. Ce que std :: copy peut réellement envoyer (le cas échéant) est défini par l'implémentation, il n'est donc pas utile de mentionner des détails sans mentionner l'implémentation.
Fred Nurk
1
Bien qu'un programme simple pour reproduire ce comportement, compilé avec -O3 sous GCC me montre un fichier memcpy. Cela me porte à croire que GCC vérifie s'il y a chevauchement de mémoire.
jweyrich
1
@Konrad: la norme std::copypermet le chevauchement dans un sens mais pas dans l'autre. Le début de la sortie ne peut pas se trouver dans la plage d'entrée, mais le début de l'entrée peut se trouver dans la plage de sortie. C'est un peu étrange, car l'ordre des affectations est défini et un appel peut être UB même si l'effet de ces affectations, dans cet ordre, est défini. Mais je suppose que la restriction permet des optimisations de vectorisation.
Steve Jessop
24

Toujours utiliser std::copycar il memcpyest limité uniquement aux structures POD de style C, et le compilateur remplacera probablement les appels à std::copyparmemcpy si les cibles sont en fait POD.

De plus, std::copypeut être utilisé avec de nombreux types d'itérateurs, pas seulement avec des pointeurs. std::copyest plus flexible pour aucune perte de performance et est clairement le gagnant.

Chiot
la source
Pourquoi voudriez-vous copier autour des itérateurs?
Atmocreations
3
Vous ne copiez pas les itérateurs, mais plutôt la plage définie par deux itérateurs. Par exemple, std::copy(container.begin(), container.end(), destination);copiera le contenu de container(tout entre beginet end) dans le tampon indiqué par destination. std::copyne nécessite pas de manigances comme &*container.begin()ou &container.back() + 1.
David Stone
16

En théorie, memcpypourrait avoir une légère , imperceptible , infinitésimale , l' avantage de la performance, seulement parce qu'il n'a pas les mêmes exigences que std::copy. Depuis la page de manuel de memcpy:

Pour éviter les débordements, la taille des tableaux pointés par les paramètres de destination et de source doit être d'au moins nombre d'octets et ne doit pas se chevaucher (pour les blocs de mémoire qui se chevauchent, memmove est une approche plus sûre).

En d'autres termes, memcpypeut ignorer la possibilité de chevauchement des données. (Passer des tableaux qui memcpyse chevauchent à est un comportement indéfini.) Il memcpyn'est donc pas nécessaire de vérifier explicitement cette condition, alors qu'il std::copypeut être utilisé tant que le OutputIteratorparamètre n'est pas dans la plage source. Notez que ce n'est pas la même chose que de dire que la plage source et la plage de destination ne peuvent pas se chevaucher.

Donc, comme std::copyles exigences sont quelque peu différentes, en théorie, il devrait être légèrement (avec un accent extrême sur légèrement ) plus lent, car il vérifiera probablement le chevauchement des tableaux C, ou bien déléguera la copie des tableaux C àmemmove , qui doit effectuer le vérifier. Mais en pratique, vous (et la plupart des profileurs) ne détecterez probablement même aucune différence.

Bien sûr, si vous ne travaillez pas avec des POD , vous ne pouvez pas utiliser de memcpytoute façon.

Charles Salvia
la source
7
Ceci est vrai pour std::copy<char>. Mais std::copy<int>peut supposer que ses entrées sont alignées sur int. Cela fera une bien plus grande différence, car cela affecte chaque élément. Le chevauchement est un contrôle unique.
MSalters
2
@MSalters, vrai, mais la plupart des implémentations memcpyque j'ai vues vérifient l'alignement et tentent de copier des mots plutôt que octet par octet.
Charles Salvia
1
std :: copy () peut également ignorer le chevauchement de la mémoire. Si vous voulez prendre en charge le chevauchement de la mémoire, vous devez écrire vous-même la logique pour appeler std :: reverse_copy () dans les situations appropriées.
Cygon
2
Il y a un argument opposé qui peut être avancé: en passant par l' memcpyinterface, il perd les informations d'alignement. Par conséquent, memcpydoit effectuer des vérifications d'alignement au moment de l'exécution pour gérer les débuts et les fins non alignés. Ces chèques peuvent être bon marché mais ils ne sont pas gratuits. Alors que std::copypeut éviter ces contrôles et vectoriser. En outre, le compilateur peut prouver que les tableaux source et de destination ne se chevauchent pas et se vectorisent à nouveau sans que l'utilisateur n'ait à choisir entre memcpyet memmove.
Maxim Egorushkin
11

Ma règle est simple. Si vous utilisez C ++, préférez les bibliothèques C ++ et non C :)

UmmaGumma
la source
40
C ++ a été explicitement conçu pour permettre l'utilisation des bibliothèques C. Ce n'était pas un accident. Il est souvent préférable d'utiliser std :: copy que memcpy en C ++, mais cela n'a rien à voir avec lequel est C, et ce type d'argument est généralement la mauvaise approche.
Fred Nurk
2
@FredNurk Habituellement, vous voulez éviter les zones faibles de C où C ++ fournit une alternative plus sûre.
Phil1970
@ Phil1970 Je ne suis pas sûr que C ++ soit beaucoup plus sûr dans ce cas. Nous devons encore passer des itérateurs valides qui ne dépassent pas, etc. Je suppose que pouvoir utiliser std::end(c_arr)au lieu de c_arr + i_hope_this_is_the_right_number_of elementsest plus sûr? et peut-être plus important encore, plus clair. Et ce serait le point que j'insiste dans ce cas précis: std::copy()est plus idiomatique, plus maintenable si les types d'itérateurs changent plus tard, conduit à une syntaxe plus claire, etc.
underscore_d
1
@underscore_d std::copyest plus sûr car il copie correctement les données transmises au cas où elles ne seraient pas de type POD. memcpyse fera un plaisir de copier un std::stringobjet dans une nouvelle représentation octet par octet.
Jens
3

Juste un ajout mineur: la différence de vitesse entre memcpy()et std::copy()peut varier un peu selon que les optimisations sont activées ou désactivées. Avec g ++ 6.2.0 et sans optimisations memcpy()gagne clairement:

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

Lorsque les optimisations sont activées ( -O3), tout se ressemble à nouveau:

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

Plus le tableau est grand, moins l'effet est perceptible, mais même à N=1000 memcpy()est environ deux fois plus rapide lorsque les optimisations ne sont pas activées.

Code source (nécessite 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 */
Grumbel
la source
18
Mesurer les performances avec les optimisations désactivées est ... enfin ... à peu près inutile ... Si vous êtes intéressé par les performances, vous ne compilerez pas sans optimisations.
bolov
3
@bolov Pas toujours. Un programme relativement rapide en cours de débogage est dans certains cas important à avoir.
Acorn du
2

Si vous avez vraiment besoin de performances de copie maximales (ce que vous pourriez ne pas avoir), n'utilisez aucun des deux .

Il y a beaucoup à faire pour optimiser la copie de mémoire - encore plus si vous êtes prêt à utiliser plusieurs threads / cœurs pour cela. Voir, par exemple:

Qu'est-ce qui manque / sous-optimal dans cette implémentation memcpy?

la question et certaines des réponses ont suggéré des implémentations ou des liens vers des implémentations.

einpoklum
la source
4
mode pédant: avec la mise en garde habituelle que « n'utiliser ni l'un ni l'autre » signifie si vous avez prouvé que vous avez une situation / exigence très spécifique pour laquelle aucune des fonctions standard fournies par votre implémentation n'est assez rapide ; sinon, ma préoccupation habituelle est que les personnes qui n'ont pas prouvé cela se laissent distraire par l'optimisation prématurée du code de copie au lieu des parties habituellement les plus utiles de leur programme.
underscore_d
-2

Le profilage montre cette affirmation: std::copy()est toujours aussi rapide memcpy()ou plus rapide est faux.

Mon système:

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

gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

Le code (langage: 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 () profil: main: 21: maintenant: 1422969084: 04859 écoulé: 2650 us
std :: copy () profil: main: 27: maintenant: 1422969084: 04862 écoulé: 2745 us
memcpy () écoulé 44 s std :: copy ( ) écoulé 45 s

g ++ -O3 -o test_stdcopy test_stdcopy.cpp

memcpy () profil: main: 21: maintenant: 1422969601: 04939 écoulé: 2385 us
std :: copy () profil: main: 28: maintenant: 1422969601: 04941 écoulé: 2690 us
memcpy () écoulé 27 s std :: copy ( ) écoulé 43 s

Red Alert a souligné que le code utilise memcpy de tableau en tableau et std :: copy de tableau en vecteur. Cela pourrait être une raison pour un memcpy plus rapide.

Puisqu'il y a

v.reserve (sizeof (arr1));

il ne doit y avoir aucune différence dans la copie vers le vecteur ou le tableau.

Le code est fixe pour utiliser un tableau dans les deux cas. memcpy encore plus vite:

{
    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 
imatveev13
la source
1
faux, votre profilage montre que la copie dans un tableau est plus rapide que la copie dans un vecteur. Hors sujet.
Alerte rouge
Je peux me tromper, mais dans votre exemple corrigé, avec memcpy, ne copiez-vous pas arr2 dans arr1, alors qu'avec std :: copy, vous copiez arr1 dans arr2? ... Ce que vous pourriez faire est de faire plusieurs, en alternance expériences (une fois un lot de memcpy, une fois un lot de std :: copy, puis de nouveau avec memcopy, etc., plusieurs fois.). Ensuite, j'utiliserais clock () au lieu de time (), car qui sait ce que votre PC pourrait faire en plus de ce programme. Juste mes deux cents, cependant ... :-)
paercebal
7
Donc, passer std::copyd'un vecteur à un tableau a memcpypris presque deux fois plus de temps? Ces données sont hautement suspectes. J'ai compilé votre code en utilisant gcc avec -O3, et l'assembly généré est le même pour les deux boucles. Ainsi, toute différence de temps que vous observez sur votre machine n'est que fortuite.
Alerte rouge