У меня есть нерекурсивная функция для вычисления самой длинной общей подпоследовательности, которая, кажется, хорошо работает (ghc 7.6.1
, скомпилирована с флагами -O2 -fllvm
), если я измеряю ее с помощью Criterion
в том же модуле. С другой стороны, если я преобразую функцию в модуль, экспортируйте именно эту функцию (как рекомендовано here), а затем снова измерьте с помощью Criterion, я получаю спад ~ 2x (который уходит, если я перехожу к критерию теста обратно в модуль где функция определена). Я попытался маркировать функцию с помощьюpragma, которая не имела никакого значения для измерения производительности кросс-модуля.Оптимизация перекрестных модулей в GHC
Мне кажется, что GHC может проводить анализ строгости, который хорошо работает, когда функция и основной (из которых доступна эта функция) находятся в одном модуле, но не тогда, когда они разделены. Я бы очень хотел, чтобы указатели на модульность функции, чтобы она хорошо работала при вызове из других модулей. Этот код слишком большой, чтобы вставить здесь - вы можете увидеть его here, если хотите попробовать. Небольшой пример того, что я пытаюсь сделать, это ниже (с фрагментами кода):
-- Function to find longest common subsequence given unboxed vectors a and b
-- It returns indices of LCS in a and b
lcs :: (U.Unbox a, Eq a) => Vector a -> Vector a -> (Vector Int,Vector Int)
lcs a b | (U.length a > U.length b) = lcsh b a True
| otherwise = lcsh a b False
-- This section below measures performance of lcs function - if I move it to
-- a different module, performance degrades ~2x - mean goes from ~1.25us to ~2.4us
-- on my test machine
{--
config :: Config
config = defaultConfig { cfgSamples = ljust 100 }
a = U.fromList ['a'..'j'] :: Vector Char
b = U.fromList ['a'..'k'] :: Vector Char
suite :: [Benchmark]
suite = [
bench "lcs 10" $ whnf (lcs a) b
]
main :: IO()
main = defaultMainWith config (return()) suite
--}
Попробуйте вместо этого INLINEABLE. Это может работать лучше. – Carl
@Carl, попробовал его для функции lcs. Все такой же. – Sal
Я подозреваю, что проблема заключается в том, что когда все это в одном модуле, GHC может специализировать переменную типа 'a' на' Char', поскольку она никогда не используется с каким-либо другим типом, исключая накладные расходы класса класса. Вы можете попробовать играть с прагмой 'SPECIALIZE' (или просто изменить его на' Char' вручную) и посмотреть, не имеет ли это никакого эффекта. – hammar