У нас есть решатель CFD, и во время симуляции было установлено, что на некоторых машинах он работает очень медленно, а на других - нет.При использовании Intel VTune было обнаружено, что проблема заключается в следующей строке (в Fortran):
RHOV= RHO_INF*((1.0_wp - COEFF*EXP(F0)))**(1.0_wp/(GAMM - 1.0_wp))
При детализации с помощью VTune проблема была обнаружена на сборочной линии call pow
, а при трассировке стекапоказал, что использует __slowpow()
.После некоторых поисков эта страница обнаружилась с жалобами на то же самое.
На машине с libc версии 2.12 имитация заняла 18 секунд.На машине с libc версии 2.14 моделирование заняло 0 секунд.
Основываясь на информации на вышеупомянутой странице, проблема возникает, когда основание для pow()
близко к 1,0.Таким образом, мы сделали еще один простой тест, в котором мы масштабировали базу по произвольному числу до pow()
, а затем делили на число, возведенное в показатель степени после вызова pow()
.Это снизило время выполнения с 18 секунд до 0 секунд с libc 2.12.
Однако нецелесообразно помещать это во весь код, где мы делаем a**b
.Как можно было бы заменить функцию pow()
в libc?Например, я хотел бы, чтобы сборочная линия call pow
, сгенерированная компилятором Fortran, вызывала пользовательскую функцию pow()
, которую мы пишем, которая выполняет масштабирование, вызывает libc pow()
, а затем делит на масштабирование.Как создать промежуточный слой, прозрачный для компилятора?
Редактировать
Чтобы уточнить, мы ищем что-то вроде (псевдокод):
double pow(a,b) {
a *= 5.0
tmp = pow_from_libc(a,b)
return tmp/pow_from_libc(5.0, b)
}
Можно ли загрузитьpow
из libc и переименовать его в нашей пользовательской функции, чтобы избежать конфликтов имен?Если файл customPow.o
может переименовать pow
из libc, что произойдет, если libc все еще нужен для других целей?Может ли это вызвать конфликт имен между pow
в customPow.o
и pow
в libc?