2009-11-21 11 views
7

típico strlen() atraviesa desde el primer carácter hasta que encuentra \0. Esto requiere que atraviese cada personaje. En sentido algorítmico, es O (N).strlen más rápido?

¿Hay alguna manera más rápida de hacerlo cuando la entrada está vagamente definida? Me gusta: la longitud sería menor que 50, o la longitud sería de alrededor de 200 caracteres.

Pensé en bloques de búsqueda y todo pero no obtuve ninguna optimización.

+8

seguro. 'return 4;'. ¡Garantizado para ser rapidísimo! El número fue elegido por la tirada de dados. – Geo

+1

@Geo [Lindo] (https://xkcd.com/221/), pero eso no implementa 'strlen' para la gran mayoría de las entradas. – imallett

Respuesta

17

En realidad, glibc's implementation de strlen es un ejemplo interesante del enfoque de vectorización.Es peculiar ya que no usa instrucciones vectoriales, pero encuentra una manera de usar solo instrucciones ordinarias en palabras de 32 o 64 bits del búfer.

+0

¡muy listo! –

+0

Por otro lado, al menos en x86/x86_64 y gcc, obtendrá el compilador incorporado de todos modos. – LnxPrgr3

+0

Sí, debe darle otro nombre si desea asegurarse de que la versión utilizada sea suya. Si va a hacer esto, también podría asegurarse de que todas las cadenas en las que se pase su versión estén alineadas con la palabra (si es posible) y elimine por completo el bucle char por bote inicial. –

22

Sure. Mantenga un registro de la longitud mientras escribe en la cadena.

+9

+1: Hooray pascal! –

+1

+1: Hooray Fortran (y no permite cambiarlo de ninguna manera después de la declaración) –

+0

hice grandes mejoras en strcat usando esta técnica – Mandrake

6

La respuesta corta: no.

La respuesta más larga: ¿realmente crees que si hubiera una manera más rápida de verificar la longitud de cadena para las cadenas de C barebones, algo tan comúnmente utilizado como la biblioteca de cadenas C ya no lo habría incorporado?

Sin algún tipo de conocimiento adicional sobre una cadena, debe verificar cada carácter. Si está dispuesto a mantener esa información adicional, puede crear un struct que almacene la longitud como un campo en la estructura (además de la matriz de caracteres real/puntero para la cadena), en cuyo caso podría hacer la longitud búsqueda de tiempo constante, pero tendría que actualizar ese campo cada vez que modificó la cadena.

+0

Entonces tendríamos cadenas de Pascal de nuevo. :) – wadesworld

+1

Pero probablemente tendríamos menos desbordamientos de búfer (si estaban incorporados al lenguaje o si se utilizaban de forma coherente)) - ¡lo cual sería una buena cosa! –

9

Obviamente, si su cadena tiene una longitud mínima conocida, puede comenzar su búsqueda en esa posición.

Más allá de eso, no hay nada que puedas hacer; Si intenta hacer algo inteligente y encuentra un byte \0, aún necesita verificar cada byte entre el inicio de la cadena y ese punto para asegurarse de que no haya habido un \0 anterior.

Eso no quiere decir que strlen no se puede optimizar. Se puede canalizar y se puede procesar procesadores de tamaño de palabra o vector con cada comparación. En la mayoría de las arquitecturas, una combinación de estos y otros enfoques producirán una aceleración sustancial de factor constante sobre un circuito ingenuo de comparación de bytes. Por supuesto, en las plataformas más maduras, el sistema strlen ya está implementado usando estas técnicas.

3

Puede intentar usar la vectorización. No estoy seguro si el compilador podrá realizarlo, pero lo hice manualmente (usando intrínsecos). Pero podría ayudarte solo para cadenas largas.

Use stl strings, es más seguro y std :: string class contiene su longitud.

+0

¿Cómo ayudaría la vectorización? Incluso si el búfer fuera, por ejemplo, 4 KB, no hay garantía sobre el contenido de la cadena después del primer nulo, entonces si la vectorización comenzó 4 operaciones (¿hilos?) En los límites de 1 KB, no hay forma de saber a partir de se vería una compensación distinta de cero. Supongo que el resultado debería ser el mínimo de los 4 valores devueltos, donde los subprocesos de desplazamiento distintos de cero tendrían que agregar su posición de inicio a la longitud devuelta. –

+0

Creo que Elalfer propone asignar cada byte consecutivo a un vector que se va a verificar como un todo, y luego desplazar el rastreo de cadena de la longitud del vector. Eso definitivamente funcionaría, suponiendo que tienes una arquitectura basada en vectores. –

+2

@Jonathan Vectorization no está utilizando hilos! Vectorizar significa usar el modelo de programación SIMD para verificar bytes consecutivos para cero simultáneamente. http://en.wikipedia.org/wiki/SIMD Ayuda a que la alineación del vector siempre los ajuste en una sola página. Esta implementación típicamente desborda el búfer pero no es capturado por la MMU. Encontramos estos desbordamientos de búfer benignos en el analizador en el que trabajo. Ver también http://tsunanet.net/~tsuna/strlen.c.html para una impresionante implementación de C sin instrucciones vectoriales especiales. –

4

Jack,

strlen obras de buscar la terminación '\ 0', aquí es una implementación tomada de OpenBSD:

size_t 
strlen(const char *str) 
{ 
     const char *s; 

     for (s = str; *s; ++s) 
       ; 
     return (s - str); 
} 

Ahora, tenga en cuenta que usted sabe la longitud es de unos 200 caracteres, como tu dijiste. Digamos que comienzas en 200 y bucle arriba y abajo para un '\ 0'. Has encontrado uno en 204, ¿qué significa? ¿Que la cuerda tiene 204 caracteres de largo? ¡NO! Podría terminar antes con otro '\ 0' y todo lo que hizo fue mirar fuera de límites.

+0

Gracias por su respuesta. Como dije, la longitud se predice vagamente y puede no finalizar después del carácter 200. Además, si comenzamos a leer después del carácter 200, podríamos estar leyendo cadenas inválidas (si la cadena ha terminado alrededor de 100 caracteres ...) – Jack

+0

Link también dice mismo: http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlen.c?annotate=1.7 – Jack

3

Obtenga un procesador Core i7.

Core i7 viene con el conjunto de instrucciones SSE 4.2. Intel agregó cuatro instrucciones vectoriales adicionales para acelerar las tareas de búsqueda relacionadas con strlen y relacionadas.

Aquí están algunas ideas interesantes sobre las nuevas instrucciones:

http://smallcode.weblogs.us/oldblog/2007/11/

+0

Gracias por la respuesta. Como dice George Verghese, el aumento de hardware siempre ayuda :) – Jack