sintaxis raiz raices potencias potencia operador funcion exponente cubica cuadrada con c fortran libc pow

raiz - Sustitución de la función pow extraordinariamente lenta()



raiz cubica en c (4)

Bueno, espera ahora. La biblioteca no está llamando a __slowpow() solo para __slowpow() contigo; llama a __slowpow() porque cree que la precisión adicional es necesaria para dar un resultado preciso para los valores que le das (en este caso, base muy cercana a 1, exponente de la orden 1). Si le importa la precisión de este cálculo, debe comprender por qué es así y si es importante antes de tratar de evitarlo. Podría ser el caso que para (digamos) gran F0 negativo todo este asunto se puede redondear a 1; o puede que no, dependiendo de lo que se haga con este valor más adelante. Si alguna vez necesitas 1.d0 menos este resultado, vas a querer esa precisión extra.

Tenemos un solucionador de CFD y, mientras ejecutamos una simulación, se descubrió que funcionaba extraordinariamente lento en algunas máquinas pero no en otras. Usando Intel VTune, se encontró que la siguiente línea era el problema (en Fortran):

RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))

__slowpow() con VTune, el problema se remontaba a la línea de ensamblaje call pow y al rastrear la pila, mostraba que estaba usando __slowpow() . Después de algunas búsquedas, esta página apareció quejándose de lo mismo.

En la máquina con la versión 2.12 de libc, la simulación tomó 18 segundos. En la máquina con la versión 2.14 de libc, la simulación tomó 0 segundos.

De acuerdo con la información en la página mencionada, el problema surge cuando la base para pow() está cerca de 1.0. Así que hicimos otra prueba simple donde escalamos la base por un número arbitrario antes del pow() y luego dividimos por el número elevado al exponente después de la llamada pow() . Esto redujo el tiempo de ejecución de 18 segundos a 0 segundos con el libc 2.12 también.

Sin embargo, no es práctico poner esto sobre el código donde hacemos a**b . ¿Cómo se podría reemplazar la función pow() en libc? Por ejemplo, me gustaría que la cadena de montaje call pow generada por el compilador Fortran para llamar a una función pow() que escribamos que hace la escala, llama a libc pow() y luego se divide por la escala. ¿Cómo se puede crear una capa intermedia transparente para el compilador?

Editar

Para aclarar, estamos buscando algo como (pseudo-código):

double pow(a,b) { a *= 5.0 tmp = pow_from_libc(a,b) return tmp/pow_from_libc(5.0, b) }

¿Es posible cargar el pow de libc y cambiarle el nombre en nuestra función personalizada para evitar los conflictos de nomenclatura? Si el archivo customPow.o podría cambiar el nombre de pow de libc, ¿qué ocurre si aún se necesita libc para otras cosas? ¿ customPow.o causaría un conflicto de nombres entre pow en customPow.o y pow in libc?


Probé esto yo mismo, y de hecho si compilo el programa de prueba desde la página que enlazas usa call pow en el código de ensamblaje. Sin embargo, al compilar con optimization -ffast-math no hay llamadas a pow, pero el resultado es ligeramente diferente.


Simplemente escriba su propia función pow , coloque el archivo .o en un archivo de biblioteca estática libmypow.a en algún lugar de la ruta de la biblioteca del enlazador, y pase -lmypow cuando lo enlace.


pow(a,b) es lo mismo que exp(b*ln(a)) , tal vez esa sustitución funcione para usted.