diff --git a/src/Cluster.hs b/src/Cluster.hs index 2ae8e86892bdb9796e6be3eaaf587f7fdc887388..8e208184754af643284f79ddc25e39c82c60f624 100644 --- a/src/Cluster.hs +++ b/src/Cluster.hs @@ -22,6 +22,7 @@ module Cluster , computeSolution , applySolution , printSolution + , printSolutionLine , printNodes -- * Balacing functions , checkMove @@ -423,9 +424,7 @@ checkMove nodes_idx ini_tbl victims = if length best_plc == length ini_plc then -- no advancement ini_tbl else - -- FIXME: replace 100 with a real constant - if (length best_plc > 100) then best_tbl - else checkMove nodes_idx best_tbl victims + best_tbl {- | Auxiliary function for solution computation. diff --git a/src/hbal.hs b/src/hbal.hs index 7b98d19400b7f41dc4a5ba045c2ab5e42ff59a1a..352fbb4b7910735f2662cd7553b49ba11eebf674 100644 --- a/src/hbal.hs +++ b/src/hbal.hs @@ -27,7 +27,7 @@ data Options = Options , optOneline :: Bool , optNodef :: FilePath , optInstf :: FilePath - , optMaxRounds :: Int + , optMaxLength :: Int , optMaster :: String } deriving Show @@ -39,7 +39,7 @@ defaultOptions = Options , optOneline = False , optNodef = "nodes" , optInstf = "instances" - , optMaxRounds = -1 + , optMaxLength = -1 , optMaster = "" } @@ -47,12 +47,17 @@ defaultOptions = Options we find a valid solution or we exceed the maximum depth. -} -iterateDepth :: Cluster.Table -- The starting table - -> Int -- ^ Current round - -> Int -- ^ Max rounds +iterateDepth :: Cluster.Table -- ^ The starting table + -> Int -- ^ Remaining length + -> [(Int, String)] -- ^ Node idx to name list + -> [(Int, String)] -- ^ Inst idx to name list + -> Int -- ^ Max node name len + -> Int -- ^ Max instance name len + -> [[String]] -- ^ Current command list -> Bool -- ^ Wheter to be silent - -> IO Cluster.Table -- The resulting table -iterateDepth ini_tbl cur_round max_rounds oneline = + -> IO (Cluster.Table, [[String]]) -- ^ The resulting table and + -- commands +iterateDepth ini_tbl max_rounds ktn kti nmlen imlen cmd_strs oneline = let Cluster.Table ini_nl ini_il ini_cv ini_plc = ini_tbl all_inst = Container.elems ini_il node_idx = Container.keys ini_nl @@ -60,32 +65,24 @@ iterateDepth ini_tbl cur_round max_rounds oneline = (Cluster.Table _ _ fin_cv fin_plc) = fin_tbl ini_plc_len = length ini_plc fin_plc_len = length fin_plc - allowed_next = (max_rounds < 0 || cur_round < max_rounds) + allowed_next = (max_rounds < 0 || length fin_plc < max_rounds) in do - unless oneline $ printf " - round %d: " cur_round - hFlush stdout - let msg = - if fin_cv < ini_cv then - if not allowed_next then - printf "%.8f, %d moves (stopping due to round limit)\n" - fin_cv - (fin_plc_len - ini_plc_len) - else - printf "%.8f, %d moves\n" fin_cv - (fin_plc_len - ini_plc_len) - else - "no improvement, stopping\n" - unless oneline $ do - putStr msg + let + (sol_line, cmds) = Cluster.printSolutionLine ini_il ktn kti + nmlen imlen (head fin_plc) + upd_cmd_strs = cmds:cmd_strs + unless (oneline || fin_plc_len == ini_plc_len) $ do + putStrLn sol_line hFlush stdout (if fin_cv < ini_cv then -- this round made success, try deeper if allowed_next - then iterateDepth fin_tbl (cur_round + 1) max_rounds oneline + then iterateDepth fin_tbl max_rounds ktn kti + nmlen imlen upd_cmd_strs oneline -- don't go deeper, but return the better solution - else return fin_tbl + else return (fin_tbl, upd_cmd_strs) else - return ini_tbl) + return (ini_tbl, cmd_strs)) -- | Options list and functions options :: [OptDescr (Options -> Options)] @@ -108,9 +105,10 @@ options = , Option ['m'] ["master"] (ReqArg (\ m opts -> opts { optMaster = m }) "ADDRESS") "collect data via RAPI at the given ADDRESS" - , Option ['r'] ["max-rounds"] - (ReqArg (\ i opts -> opts { optMaxRounds = (read i)::Int }) "N") - "do not run for more than R rounds(useful for very unbalanced clusters)" + , Option ['l'] ["max-length"] + (ReqArg (\ i opts -> opts { optMaxLength = (read i)::Int }) "N") + "cap the solution at this many moves (useful for very unbalanced \ + \clusters)" ] -- | Command line parser, using the 'options' structure. @@ -167,22 +165,28 @@ main = do ini_cv (Cluster.printStats nl) unless oneline $ putStrLn "Trying to minimize the CV..." - fin_tbl <- iterateDepth ini_tbl 1 (optMaxRounds opts) oneline + let mlen_fn = maximum . (map length) . snd . unzip + imlen = mlen_fn kti + nmlen = mlen_fn ktn + + (fin_tbl, cmd_strs) <- iterateDepth ini_tbl (optMaxLength opts) + ktn kti nmlen imlen [] oneline let (Cluster.Table fin_nl _ fin_cv fin_plc) = fin_tbl ord_plc = reverse fin_plc - unless oneline $ printf "Final coefficients: overall %.8f, %s\n" - fin_cv - (Cluster.printStats fin_nl) + unless oneline $ do + (if null fin_plc + then printf "No solution found\n" + else printf "Final coefficients: overall %.8f, %s\n" + fin_cv (Cluster.printStats fin_nl)) unless oneline $ printf "Solution length=%d\n" (length ord_plc) - let (sol_strs, cmd_strs) = Cluster.printSolution il ktn kti ord_plc - unless oneline $ putStr $ unlines $ sol_strs when (optShowCmds opts) $ do putStrLn "" putStrLn "Commands to run to reach the above solution:" - putStr $ unlines $ map (" echo gnt-instance " ++) $ concat cmd_strs + putStr $ unlines $ map (" echo gnt-instance " ++) + $ concat $ reverse cmd_strs when (optShowNodes opts) $ do let (orig_mem, orig_disk) = Cluster.totalResources nl