2010-01-13 15 views
6

Tengo una biblioteca escrita en C y tengo 2 aplicaciones escritas en C++ y C. Esta biblioteca es una biblioteca de comunicación, entonces de las llamadas a la API se parece a esto:¿Por qué mi aplicación C++ es más rápida que mi aplicación C (usando la misma biblioteca) en un Core i7

int source_send(source_t* source, const char* data); 

En la aplicación del código C hace algo como esto:

source_t* source = source_create(); 
for(int i = 0; i < count; ++i) 
    source_send(source, "test"); 

Donde como la aplicación C++ hace esto:

struct Source 
{ 
    Source() 
    { 
     _source = source_create(); 
    } 

    bool send(const std::string& data) 
    { 
     source_send(_source, data.c_str()); 
    } 

    source_t* _source; 
}; 

int main() 
{ 
    Source* source = new Source(); 
    for(int i = 0; i < count; ++i) 
     source->send("test"); 
} 

En un Intel Core i7, el código C++ produce casi exactamente un 50% más de mensajes por segundo .. Mientras que en un Intel Core 2 Duo produce casi exactamente la misma cantidad de mensajes por segundo. (El núcleo i7 tiene 4 núcleos con 2 hilos de procesamiento cada uno)

Tengo curiosidad por saber qué tipo de magia realiza el hardware para lograrlo. Tengo algunas teorías, pero pensé que iba a conseguir una verdadera respuesta :)

Editar: Información adicional de los comentarios

Compiler es visual C++, así que esto es una caja de ventanas (dos de ellos)

La implementación de la biblioteca de comunicación crea un nuevo hilo para enviar mensajes. El source_create es lo que crea este hilo.

+0

¿Compilador? Configuración del compilador? Tiempo de ejecución? Comparar el código de objeto emitido? –

+0

¿Está compilando la biblioteca C también? ¿O ya está compilado para ti? ¿Source_send() se define en línea? –

+0

Tengo dificultades para colocar esto en el compilador. Estoy usando Visual Studio, por lo que debe generar código que funcione en todas las máquinas Windows, independientemente de los núcleos. Ahora, si estaba compilando con gcc -mtune = native podríamos tener algo, pero no es el caso – Charles

Respuesta

7

Al examinar su código fuente solo, no veo ningún motivo por el cual el código C++ deba ser más rápido.

Lo siguiente que haría es verificar el código de ensamblado que se está generando. Si está utilizando una cadena de herramientas GNU, tiene un par de maneras de hacerlo.

Puede solicitar a gcc y g ++ que envíen el código de ensamblado a través del argumento de la línea de comando -S. Asegúrese de que luego de agregar ese argumento, utilice exactamente los mismos argumentos de línea de comandos que hace para una compilación regular.

Una segunda opción es cargar su programa con gdb y usar el comando disas.

Buena suerte.

actualización

Usted puede hacer lo mismo con la cadena de herramientas Microsoft.

Para obtener el compilador al ensamblaje de salida, puede usar /FA or /FAs. El primero debería mostrar el ensamblaje solo mientras que el segundo mezclará el ensamblaje y la fuente (lo que debería facilitar el seguimiento).

En cuanto al uso del depurador, una vez que haya iniciado el depurador en Visual Studio, vaya a "Depurar | Windows | Desmontaje" (verificado en Visual Studio 2005, otras versiones pueden variar).

+0

Lamentablemente, el proyecto aún no está listo para compilarse en Linux, pero las ideas muy buenas +1 – Charles

+0

/FA son bastante prolijas, haré una comparación y veré si puedo detectar algo – Charles

0

Core i7 tiene hiper-enhebramiento - ¿tiene habilitado HT?

Quizás el código C++ esté compilado de alguna manera para aprovechar el HT mientras que el código C no lo hace. ¿Cómo se ve el administrador de tareas cuando ejecuta su código? ¿Distribuir uniformemente la carga entre la cantidad de núcleos, o algunos núcleos al máximo?

+0

No hay subprocesos a menos que estén ocultos en la implementación de source_send, y esta característica no sería un problema de generación de código de compilación. –

+0

Hay 8 núcleos visibles en el explorador de procesos, y al procesar ambas aplicaciones, 4 ventanas muestran actividad. Si tuviera que medir el nivel, diría que la aplicación C++ usa más% cpu, pero en general parece que todos participan. – Charles

0

Simplemente una conjetura: si está compilando la fuente de la biblioteca junto con su aplicación, y las funciones C API no están declaradas "C", entonces la versión C++ puede estar utilizando una convención de llamadas diferente y de alguna manera más rápida ??

Además, si está compilando la fuente de la biblioteca junto con su aplicación, entonces ¿quizás el compilador de C++ compila su fuente de biblioteca como C++ y de alguna manera es mejor para optimizar que su compilador de C?

+0

Me he asegurado de que Visual Studio compila C código como código C Con usar extern "C" y configurar la opción/TC en el compilador – Charles

1

Lo primero que recomendaría hacer es perfilar ambas versiones y ver si hay alguna diferencia notoria.

Es la versión C copiando algo innecesariamente (podría ser una optimización sutil o no tan sutil como la optimización del valor de retorno).

Esto debería aparecer en un buen generador de perfiles, si tiene un VS SKU superior, el generador de perfiles basado en muestras está bien, si está buscando un buen analizador gratuito, Windows Performance Analyzer es increíblemente potente para Vista y hasta here's a walkthrough on using the stackwalking option

Lo primero que probablemente haría yo mismo es irrumpir en el depurador e inspeccionar el desmontaje de cada uno para ver si son notoriamente diferentes. Tenga en cuenta que hay una opción de compilación para escupir el ASM a un archivo de texto.

Seguiría esto con un perfil si no hubiera algo notoriamente obvio (como una copia adicional).

Una cosa más, si le preocupan los hiper hilos que se interponen, afine el proceso a un núcleo que no sea HT. Puede hacerlo a través del administrador de tareas en la GUI o mediante SetThreadAffinityMask.

-Rick

2

Sin ver el código completo o el conjunto de mi mejor conjetura es que el compilador de C++ se Inlining para usted. Una de las maravillas de los compiladores de C++ es la capacidad de alinear prácticamente cualquier cosa con la velocidad, y los compiladores de Microsoft son ampliamente conocidos por su línea casi hasta el punto de hincharse irrazonablemente en los ejecutables finales.

Cuestiones relacionadas