Я не очень хорошо знаю, насколько Haskell / GHC может оптимизировать код.Ниже у меня есть довольно "грубая сила" (в декларативном смысле) реализация проблемы n королев.Я знаю, что это может быть написано более эффективно, но это не мой вопрос.Дело в том, что это заставило меня задуматься о возможностях и ограничениях оптимизации GHC.
Я выразил это в том, что считаю довольно простым декларативным смыслом.Перестановки фильтров [1..n], которые удовлетворяют предикату For all indices i,j s.t j<i, abs(vi - vj) != j-i
Я надеюсь, что это тот тип вещей, который можно оптимизировать, но это также как запрос большого компилятора.
validQueens x = and [abs (x!!i - x!!j) /= j-i | i<-[0..length x - 2], j<-[i+1..length x - 1]]
queens n = filter validQueens (permutations [1..n])
oneThru x = [1..x]
pointlessQueens = filter validQueens . permutations . oneThru
main = do
n <- getLine
print $ pointlessQueens $ (read :: String -> Int) n
Это работает довольно медленно и быстро растет.n=10
занимает около секунды, а n=12
- навсегда.Без оптимизации я могу сказать, что рост является факториальным (число перестановок), умноженным на квадратичное (количество различий в предикате для проверки).Есть ли способ, которым этот код может работать лучше с помощью интеллектуальной компиляции?Я попробовал базовые ghc
варианты, такие как -O2
и не заметил существенной разницы, но я не знаю более тонких точек (просто добавил flagS)
У меня сложилось впечатление, что функция iВызов queens
не может быть оптимизирован и должен генерировать все перестановки перед фильтрацией.Есть ли у версии без очков больше шансов?С одной стороны, я чувствую, что умное понимание функций между фильтром и предикатом может отбросить некоторые явно нежелательные элементы еще до того, как они будут полностью сгенерированы, но с другой стороны, это как бы много вопросов.
Извините, если это кажется бессвязным, я думаю, у меня вопрос
- Может ли точечная версия вышеуказанной функции быть более оптимизированной для оптимизации?
- Какие шаги я могу предпринять ввремя компиляции / компоновки, чтобы стимулировать оптимизацию?
- Не могли бы вы кратко описать некоторые возможные (и противопоставить невозможным!) способы оптимизации для приведенного выше кода?В какой момент процесса они происходят?
- Есть ли какая-то особая часть вывода
ghc --make queensN -O2 -v
, на которую я должен обратить внимание?Ничто не выделяется для меня.Даже не вижу большой разницы в выводе из-за флагов оптимизации
Я не слишком обеспокоен этим примером кода, но я подумал, что написание этого заставило меня задуматься, и оно мне кажется приличным средством дляобсуждает оптимизацию.
PS - permutations
из Data.List и выглядит так:
permutations :: [a] -> [[a]]
permutations xs0 = xs0 : perms xs0 []
where
perms [] _ = []
perms (t:ts) is = foldr interleave (perms ts (t:is)) (permutations is)
where interleave xs r = let (_,zs) = interleave' id xs r in zs
interleave' _ [] r = (ts, r)
interleave' f (y:ys) r = let (us,zs) = interleave' (f . (y:)) ys r
in (y:us, f (t:y:us) : zs)