[Haskell-cafe] Performance of Knight's Tour

Daniel Fischer daniel.is.fischer at web.de
Mon Mar 1 13:05:57 EST 2010


Am Montag 01 März 2010 17:07:46 schrieb Artyom Kazak:
> Hi! I'm learning Haskell, and now I'm trying to make framework for
> solving searching problems, such as Knight's Tour. For small boards it
> answers instantly. For 7x8 board - 23 seconds. For 8x8 board - more
> than 30 minutes (it hasn't finished yet). Where is the root of the
> evil?

In the algorithm. You investigate far too many dead ends. Since for larger 
boards, the number of dead ends increases fast, larger boards take much 
much longer.
With one little change, I get
$ echo "59 59" | ./knights +RTS -s > /dev/null
./knights +RTS -s
      68,243,720 bytes allocated in the heap
       5,914,848 bytes copied during GC
      36,436,628 bytes maximum residency (6 sample(s))
       8,486,604 bytes maximum slop
              58 MB total memory in use (1 MB lost due to fragmentation)

  Generation 0:   109 collections,     0 parallel,  0.03s,  0.03s elapsed
  Generation 1:     6 collections,     0 parallel,  0.02s,  0.02s elapsed

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    0.05s  (  0.10s elapsed)
  GC    time    0.05s  (  0.05s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time    0.10s  (  0.15s elapsed)

  %GC time      50.0%  (32.2% elapsed)

  Alloc rate    1,421,744,166 bytes per MUT second

  Productivity  50.0% of total user, 31.3% of total elapsed

For a reason I don't understand, if the second dimension is 60 and the 
first is > 18, it takes much longer,

$ echo "19 60" | ./knights +RTS -A8M -H64M-s > /dev/null
./knights +RTS -A8M -H64M -s
   2,374,198,988 bytes allocated in the heap
       1,873,412 bytes copied during GC
       5,611,132 bytes maximum residency (2 sample(s))
       4,934,352 bytes maximum slop
              70 MB total memory in use (1 MB lost due to fragmentation)

  Generation 0:   281 collections,     0 parallel,  0.15s,  0.15s elapsed
  Generation 1:     2 collections,     0 parallel,  0.00s,  0.01s elapsed

  INIT  time    0.00s  (  0.00s elapsed)
  MUT   time    1.17s  (  1.21s elapsed)
  GC    time    0.15s  (  0.16s elapsed)
  EXIT  time    0.00s  (  0.00s elapsed)
  Total time    1.32s  (  1.37s elapsed)

  %GC time      11.2%  (11.6% elapsed)

  Alloc rate    2,032,579,317 bytes per MUT second

  Productivity  88.8% of total user, 85.5% of total elapsed

The magic change:

    e ((x, y), arr) p = [(t, arr // [(t, p)]) | t <- changes]
      where
        legit ps = [t | t <- allTurns ! ps, arr!t == 0]
        changes = map snd $ sort [(length $ legit t, t) | t <- allTurns ! 
(x, y), arr ! t == 0]

investigate squares with fewer options first.


More information about the Haskell-Cafe mailing list