2010-09-13 15 views

Respuesta

23

En C++ debe usar std :: copy de forma predeterminada a menos que tenga buenas razones para hacerlo de otra manera. La razón es que las clases de C++ definen su propia semántica de copia mediante el constructor de copias y el operador de asignación de copias, y de las operaciones enumeradas, solo std :: copy respeta esas convenciones.

memcpy() utiliza una copia de datos en bytes sin procesar (aunque muy optimizada para el tamaño de la línea de caché, etc.) e ignora la semántica de copia de C++ (después de todo, es una función C ...).

cblas_dcopy() es una función especializada para usar en rutinas de álgebra lineal utilizando valores de coma flotante de precisión doble. Es probable que sobresalga en eso, pero no debe considerarse de propósito general.

Si sus datos son datos de estructura de tipo POD "simples" o datos de tipo fundamental sin formato, es probable que memcpy sea lo más rápido que pueda obtener. Igual de probable, std :: copy se optimizará para usar memcpy en estas situaciones, por lo que nunca sabrá la diferencia.

En resumen, use std :: copy().

+0

Parece que 'std :: copy' usa' std :: memmove' porque los rangos se pueden solapar (en un extremo). – visitor

+0

@visitor: Probablemente cierto. Pero apuesto a que memmove() llama a memcpy() si determina que los rangos no se superponen (aritmética del puntero fácil). –

+0

He visto una implementación de memmove que simplemente hace la copia hacia atrás si la superposición causaría problemas en el futuro. – doron

0

En la mayoría de los casos, memcpy será el más rápido, ya que es el nivel más bajo y puede implementarse en código de máquina en una plataforma determinada. (Sin embargo, si su matriz contiene objetos no triviales, es posible que memcpy no haga lo correcto, por lo que puede ser más seguro quedarse con std :: copy)

Sin embargo, todo depende de qué tan bien se implanta el stdlib en el plataforma, etc. Como el estándar no indica qué tan rápido deben ser las operaciones, no hay manera de saber en un "portátil", ya que será el más rápido.

El perfil de su aplicación mostrará el ayuno en una plataforma determinada, pero solo le informará sobre la plataforma de prueba.

Sin embargo, cuando usted perfil su aplicación lo más probable es que encuentre que los problemas están en su diseño en lugar de su elección del método de copia de matriz. (Por ejemplo, ¿por qué necesita copiar matrices grandes para que coincida?)

0

Just Profile your application. Es probable que descubras que copiar no es la parte más lenta de la misma.

0

establecimiento de memoria, sin embargo, si la matriz contiene objetos no triviales, seguir con std :: copiar.

+3

Una buena ejecución de 'std :: copy' podría ser incluso más rápido para objetos básicos; 'memcpy' tiene que lidiar con las alineaciones de direcciones arbitrarias, pero' std :: copy' conoce la alineación en tiempo de compilación. –

+4

Una gran cantidad de sugerencias de rendimiento de C++ parecen incluir calificadores como "una buena implementación ... podría ser más rápido". ¿Cuántas de estas hipotéticas optimizaciones se han implementado en algún lugar, alguna vez? – Porculus

+0

@Mike Seymour; ¿Te das cuenta de que estamos hablando de copiar una matriz, es decir, un bloque continuo de memoria que contiene objetos? –

0

Tengo que pensar que los otros llamarán a memcpy(). Habiendo dicho eso, no puedo creer que haya una diferencia apreciable.

Si realmente te importa, codifica los tres y ejecuta un generador de perfiles, pero podría ser mejor considerar aspectos como la legibilidad/mantenibilidad, la excepción segura, etc.(y codifique una inserción de ensamblador mientras está en ello, no es probable que vea una diferencia)

¿Está enloquecido su programa?

Y, lo más importante, ¿cómo declaras tu matriz? (¿Qué es un conjunto de) y qué tan grande es?

0

memcpy es probablemente la forma más rápida de copiar un bloque contiguo de memoria. Esto se debe a que probablemente estará altamente optimizado para su hardware en particular. A menudo se implementa como una función de compilación incorporada.

Habiendo dicho eso, y no es probable que el objeto POD C++ sea contiguo y, por lo tanto, copiar matrices de objetos C++ usando memcpy es probable que le brinde resultados inesperados. Al copiar matrices (o colecciones) de objetos C++, std::copy utilizará la propia semántica de copia del objeto y, por lo tanto, es adecuado para su uso con objetos que no sean POD C++.

cblas_dcopy parece una copia para usar con una biblioteca específica y probablemente tenga poco uso cuando no se use esa biblioteca.

+0

¿por qué supone 'std :: copy' ser más lento que' memcpy'? – jalf

1

Utilice std :: copy a menos que la creación de perfiles le muestre un beneficio necesario para hacer lo contrario. Hace honor a la encapsulación de objetos C++, invocando constructores de copia y operadores de asignación, y la implementación podría incluir otras optimizaciones en línea como evitar una llamada a la función fuera de línea a memcpy() si el tamaño es conocido en tiempo de compilación y demasiado pequeño justifica la función llamada sobrecarga. (Algunos sistemas pueden tener macros memcpy que hacen determinaciones similares, pero en general el compilador C++ tendrá más información sobre qué optimizaciones son funcionalmente equivalentes).

FWIW/en la vieja caja Linux Tengo a mano, GCC no lo hace las optimizaciones espectacular, pero bits/type_traits.h hace que el programa pueda especificar fácilmente si std :: copia debe caer a través de memcpy():

* Copyright (c) 1997 
* Silicon Graphics Computer Systems, Inc. 
* 
* Permission to use, copy, modify, distribute and sell this software 
* and its documentation for any purpose is hereby granted without fee, 
* provided that the above copyright notice appear in all copies and    
* that both that copyright notice and this permission notice appear    
* in supporting documentation. Silicon Graphics makes no      
* representations about the suitability of this software for any    
* purpose. It is provided "as is" without express or implied warranty.   
...                    

/*                    
This header file provides a framework for allowing compile time dispatch   
based on type attributes. This is useful when writing template code.    
For example, when making a copy of an array of an unknown type, it helps   
to know if the type has a trivial copy constructor or not, to help decide  
if a memcpy can be used. 

The class template __type_traits provides a series of typedefs each of 
which is either __true_type or __false_type. The argument to 
__type_traits can be any type. The typedefs within this template will 
attain their correct values by one of these means: 
    1. The general instantiation contain conservative values which work 
     for all types. 
    2. Specializations may be declared to make distinctions between types. 
    3. Some compilers (such as the Silicon Graphics N32 and N64 compilers) 
     will automatically provide the appropriate specializations for all 
     types. 

EXAMPLE: 

//Copy an array of elements which have non-trivial copy constructors 
template <class _Tp> void 
    copy(_Tp* __source,_Tp* __destination,int __n,__false_type); 
//Copy an array of elements which have trivial copy constructors. Use memcpy. 
template <class _Tp> void 
    copy(_Tp* __source,_Tp* __destination,int __n,__true_type); 

//Copy an array of any type by using the most efficient copy mechanism 
template <class _Tp> inline void copy(_Tp* __source,_Tp* __destination,int __n) { 
    copy(__source,__destination,__n, 
     typename __type_traits<_Tp>::has_trivial_copy_constructor()); 
} 
*/ 
Cuestiones relacionadas