2009-12-25 8 views
21

Utilizzo di memcpy() quando la sovrapposizione di origine e destinazione può portare a un comportamento non definito - in questi casi è possibile utilizzare solo memmove().Quale utilizzare: memmove() o memcpy() - quando i buffer non si sovrappongono?

Ma cosa succede se non sono sicuro che i buffer si sovrappongano - esiste un motivo per utilizzare nello specifico memcpy() o nello specifico memmove()? Quale dovrei usare e perché?

+3

Oppure 'std :: copy'? ;) – jalf

+0

Non userei 'std :: copy' se la mia vita dipendesse da questo. –

+0

@Matt Joiner: Potresti spiegare perché non ti piace 'std :: copy()' così tanto? – sharptooth

risposta

32

Supponendo che un implementatore di libreria ragionevole, memcpy sia sempre veloce almeno come memmove. Tuttavia, sulla maggior parte delle piattaforme la differenza sarà minima e su molte piattaforme memcpy è solo un alias per memmove per supportare il codice legacy che chiama (erroneamente) memcpy su buffer sovrapposti.

Entrambi i codici memcpy e memmove devono essere scritti per sfruttare i carichi e gli archivi più veloci disponibili sulla piattaforma.

Per rispondere alla tua domanda: dovresti usare quello che è semanticamente corretto. Se è possibile garantire che i buffer non si sovrappongano, è necessario utilizzare memcpy. Se non è possibile garantire che i buffer non si sovrappongano, è necessario utilizzare memmove.

+0

+1. Mi piace soprattutto il contrappunto "presuntuoso" della mia risposta :-) – paxdiablo

+0

Nitpick: 'memcpy' e' memmove' dovrebbero essere scritti per sfruttare i carichi e i negozi 'non allineati 'più veloci disponibili sulla piattaforma. Se sai che i tuoi buffer sono allineati correttamente, puoi ottenere prestazioni molto migliori usando cose come MMX, che copiano unità di dati molto più grandi alla volta. –

+0

@Adam: in generale si può disporre di utilizzare carichi e depositi allineati nella memcopy, copiando prima alcune unità più piccole per ottenere l'allineamento appropriato. Se i buffer non hanno allineamento simile, sarà necessario applicare alcuni shift o permute prima di archiviare, ma questo è più veloce rispetto all'utilizzo di accessi di memoria non allineati su molte architetture. –

29

memcpy() non ha alcuna gestione speciale per i buffer sovrapposti, quindi manca di alcuni controlli quindi è più veloce di memmove().

Anche su alcune architetture memcpy() può trarre vantaggio dall'utilizzo delle istruzioni della CPU per lo spostamento di blocchi di memoria, cosa che non è possibile utilizzare memmove().

+0

la tua modifica ha catturato quello che volevo dire, +1. – falstro

+0

+1, per menzionare le istruzioni della CPU. – MAK

+0

Anche su un'architettura RISC, vi sono spesso operazioni di blocco dei blocchi da cui può essere utile memcpy(). PowerPC ha VMX, per esempio. – Crashworks

5

Se ti interessa che funzioni meglio, è necessario testarlo sulla piattaforma di destinazione. Niente nello standard impone come vengono implementate le funzioni e, mentre può sembrare logico che un controllo non memcpy sia più veloce, questa non è affatto una certezza.

E 'del tutto possibile, anche se improbabile, che la persona che ha scritto memmove per il vostro particolare compilatore era un genio certificata, mentre la povera anima che ha ottenuto l'incarico di scrivere memcpy era lo scemo del villaggio :-)

Anche se, in realtà, trovo difficile immaginare che lo memmove potrebbe essere più veloce di memcpy, non ne scordo la possibilità. Misura, non indovinare.

+1

'memcpy' ha il qualificatore restrittivo sui suoi argomenti, non' memmove'. (Codifica precisamente il fatto che i buffer non si sovrappongono). –

+0

D'Oh! Hai ragione, naturalmente, @StephenC, li ho presi nel modo sbagliato. Rimosso quel twaddle dalla mia risposta :-) – paxdiablo

2

Su una piattaforma ARM su cui sto lavorando, memmove era 3 volte più veloce di memcpy per un breve carico non assegnato. Dato che memcpy e memmove sono l'unico meccanismo di punzonatura di tipo veramente portatile, avresti pensato che sarebbe stato un controllo da parte del compilatore prima di provare a usare NEON per farlo.

Problemi correlati