Pregunta

Me gustaría copiar una secuencia relativamente corta de la memoria (menos de 1 KB, típicamente 2-200 bytes) en una función crítica del tiempo. El mejor código para esta en el lado de la CPU parece estar rep movsd. Sin embargo, yo de alguna manera no puedo hacer que mi compilador para generar el código. Yo esperaba (y vagamente recuerdo haber visto algo así) utilizando memcpy había de hacer esto usando el compilador intrínsecos incorporadas, pero basado en el desmontaje y la depuración parece compilador está utilizando llamada a memcpy / implementación de la biblioteca memmove lugar. También esperaba que el compilador podría ser suficiente para reconocer siguiente bucle y utilizar rep movsd por sí inteligente, pero parece que no lo hace.

char *dst;
const char *src;
// ...
for (int r=size; --r>=0; ) *dst++ = *src++;

¿Hay alguna manera de hacer que el compilador de Visual Studio para generar la secuencia rep movsd con excepción de usar ensamblador en línea?

¿Fue útil?

Solución 3

Uso memcpy con un tamaño constante

Lo que he encontrado por su parte:

compilador utilizará intrínseca cuando el tamaño de bloque de copiado es compilar tiempo conocido. Cuando no lo es, es la implementación de la biblioteca llamadas. Cuando se conoce el tamaño, el código generado es muy agradable, seleccionado en función del tamaño. Puede ser un solo mov, o movsd, o movsd seguido de movsb, según sea necesario.

Parece que si realmente quiero usar movsb o movsd siempre, incluso con un tamaño "dinámica" Voy a tener que usar ensamblador en línea o intrínseco especial (véase más adelante). Sé que el tamaño es "bastante corta", pero el compilador no lo sé y no puedo comunicar esto a él - incluso he tratado de usar __assume (tamaño <16), pero no es lo suficientemente

.

código Demo, compilar con "-Ob1 (expansión para inline solamente):

  #include <memory.h>

  void MemCpyTest(void *tgt, const void *src, size_t size)
  {
    memcpy(tgt,src,size);
  }

  template <int size>
  void MemCpyTestT(void *tgt, const void *src)
  {
    memcpy(tgt,src,size);
  }

  int main ( int argc, char **argv )
  {
    int src;
    int dst;
    MemCpyTest(&dst,&src,sizeof(dst));
    MemCpyTestT<sizeof(dst)>(&dst,&src);
    return 0;
  }

intrínsecos Especializados

He encontrado recientemente existe manera muy sencilla cómo hacer que Visual Studio personajes copia compilador utilizando movsd - muy simples y naturales: los intrínsecos usando. Siguiendo los intrínsecos puede venir a mano:

Otros consejos

Varias preguntas vienen a la mente.

En primer lugar, ¿cómo se sabe movsd sería más rápido? ¿Ha mirado su latencia / rendimiento? La arquitectura x86 está llena de instrucciones antiguas enrevesada que no deben utilizarse porque simplemente no son muy eficientes en la moderna CPU.

En segundo lugar, ¿qué ocurre si se utiliza std::copy lugar de establecimiento de memoria? std::copy es potencialmente más rápido, ya que se puede especializar en tiempo de compilación para el tipo de datos específico.

Y en tercer lugar, ¿ha habilitado las funciones intrínsecas en las propiedades del proyecto -> C / C ++ -> Optimización

Por supuesto Asumo otras optimizaciones también están activados.

¿Está ejecutando una construcción optimizada? No va a utilizar una intrínseca a menos optimización está activada. También debe notarse que probablemente utilizará un mejor lazo de copia de movsd representante. Se debe tratar de utilizar MMX, por lo menos, para realizar una de 64 bits en una copia de tiempo. De hecho 6 o 7 años atrás escribí un bucle de copia optimizado MMX para hacer este tipo de cosas. Desafortunadamente memcpy intrínseca del compilador superó mi copia MMX en un 1%. Eso realmente me enseñó a no hacer suposiciones acerca de lo que el compilador está haciendo.

¿Ha programado establecimiento de memoria? En las últimas versiones de Visual Studio, la aplicación utiliza memcpy SSE2 ... que debería ser más rápido que rep movsd. Si el bloque está copiando es de 1 KB, entonces no es realmente un problema que el compilador no está utilizando una intrínseca desde el momento de la llamada a función será insignificante en comparación con el tiempo de la copia.

Tenga en cuenta que el fin de utilizar movsd, src debe apuntar a una memoria alineado con límite de 32 bits y su longitud debe ser un múltiplo de 4 bytes.

Si lo es, ¿por qué el código de uso en lugar de char * int * o algo? Si no lo es, su pregunta es discutible.

Si cambia char * a int *, que podría obtener un mejor resultado de std::copy.

Editar: tiene que se ha medido que la copia es el cuello de botella

Uso memcpy. Este problema ya ha sido resuelto.

Para su información movsd representante no es siempre la mejor, movsb representante puede ser más rápido en algunas circunstancias y con SSE y similares es la mejor movntq [edi], xmm0. Incluso se puede optimizar aún más de gran cantidad de memoria en el uso de la página localidad por el movimiento de datos a un búfer y luego moverlo a su destino.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top