Степень оптимизации GHC

Я не очень хорошо знаю, насколько Haskell / GHC может оптимизировать код. Ниже у меня есть довольно "грубая сила" (в декларативном смысле) реализация задачи n ферзей. Я знаю, что это можно написать более эффективно, но вопрос не в этом. Это заставило меня задуматься о возможностях и ограничениях оптимизации GHC.

Я выразил это в том, что я считаю довольно простым декларативным смыслом. Отфильтруйте перестановки [1..n], которые удовлетворяют предикату Для всех индексов i, j st j Я надеюсь, что это то, что может быть оптимизированным, но это также похоже на то, что от компилятора требуется много усилий.

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 , и не заметил значительной разницы, но я не знаю более тонких моментов (просто добавил флажки)

Мой создается впечатление, что функция, которую я вызываю ферзей , не может быть оптимизирована и должна генерировать все перестановки перед фильтром. У безточечной версии больше шансов?С одной стороны, мне кажется, что умное понимание функций между фильтром и предикатом могло бы отбросить некоторые явно нежелательные элементы еще до того, как они будут полностью сгенерированы, но с другой стороны, мне кажется, что спросить очень много.

Извините, если это кажется бессвязным, я предполагаю, что у меня такой вопрос:

  1. Можно ли оптимизировать бесточечную версию вышеупомянутой функции?
  2. Какие шаги я мог бы предпринять во время make / compile / link, чтобы стимулировать оптимизацию?
  3. ] Не могли бы вы вкратце описать некоторые возможные (и отличные от невозможного!) Средства оптимизации приведенного выше кода? В какой момент процесса это происходит?
  4. Есть ли какая-то конкретная часть вывода ghc --make queensN -O2 -v , на которую мне следует обратить внимание? Для меня ничего не выделяется. Даже не вижу большой разницы в выводе из-за флагов оптимизации

. Я не слишком озабочен этим примером кода, но я думал, что его написание заставило меня задуматься, и это кажется мне достойным средством для обсуждения оптимизации.

PS - перестановки взяты из 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)

11
задан jon_darkstar 24 June 2011 в 19:20
поделиться