mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-05-23 09:52:55 -06:00
Parallel compilation: "gf -make -j" and "gf -make -j=n" now work as expected
* "gf -make -j=n" uses n parallel threads. * "gf -make -j" adapts to the number of processors in the system. This mimics how "cabal build -j" and "ghc --make -j" works. Support for this is implemented in the new module GF.System.Concurrency and it depends on the function Control.Concurrent.setNumCapabilities, which is only available in GHC>=7.6 (base>=4.6). GF can still be compiled with GHC<7.6, but then you have to use +RTS -N -RTS to take advantage of multicore processors. To detect the number of processors in the system, the code depends on a foreign import of a C function in the GHC run-time system.
This commit is contained in:
2
gf.cabal
2
gf.cabal
@@ -254,11 +254,11 @@ Library
|
|||||||
GF.Speech.SRGS_XML
|
GF.Speech.SRGS_XML
|
||||||
GF.Speech.VoiceXML
|
GF.Speech.VoiceXML
|
||||||
GF.System.Catch
|
GF.System.Catch
|
||||||
|
GF.System.Concurrency
|
||||||
GF.System.Console
|
GF.System.Console
|
||||||
GF.System.Directory
|
GF.System.Directory
|
||||||
GF.System.Process
|
GF.System.Process
|
||||||
GF.System.Signal
|
GF.System.Signal
|
||||||
-- GF.System.UseSignal
|
|
||||||
GF.Text.Clitics
|
GF.Text.Clitics
|
||||||
GF.Text.Coding
|
GF.Text.Coding
|
||||||
GF.Text.Lexing
|
GF.Text.Lexing
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import Prelude hiding (catch)
|
|||||||
import Control.Monad(join,ap,when,unless)
|
import Control.Monad(join,ap,when,unless)
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
import GF.Infra.Concurrency
|
import GF.Infra.Concurrency
|
||||||
|
import GF.System.Concurrency
|
||||||
import System.FilePath
|
import System.FilePath
|
||||||
import qualified GF.System.Directory as D
|
import qualified GF.System.Directory as D
|
||||||
import GF.System.Catch(catch,try)
|
import GF.System.Catch(catch,try)
|
||||||
@@ -27,11 +28,12 @@ import qualified Data.ByteString.Lazy as BS
|
|||||||
-- the broken PGF files that can result from mixing different modes in the
|
-- the broken PGF files that can result from mixing different modes in the
|
||||||
-- same concrete syntax.
|
-- same concrete syntax.
|
||||||
--
|
--
|
||||||
-- The first argument is supposed to be the number of jobs to run in
|
-- The first argument controls the number of jobs to run in
|
||||||
-- parallel, but this has not been implemented yet. Instead you have to
|
-- parallel. This works if GF was compiled with GHC>=7.6, otherwise you have to
|
||||||
-- use the GHC run-time flag @+RTS -N -RTS@ to enable parallelism.
|
-- use the GHC run-time flag @+RTS -N -RTS@ to enable parallelism.
|
||||||
parallelBatchCompile jobs opts rootfiles0 =
|
parallelBatchCompile jobs opts rootfiles0 =
|
||||||
do rootfiles <- mapM canonical rootfiles0
|
do setJobs jobs
|
||||||
|
rootfiles <- mapM canonical rootfiles0
|
||||||
lib_dir <- canonical =<< getLibraryDirectory opts
|
lib_dir <- canonical =<< getLibraryDirectory opts
|
||||||
filepaths <- mapM (getPathFromFile lib_dir opts) rootfiles
|
filepaths <- mapM (getPathFromFile lib_dir opts) rootfiles
|
||||||
let groups = groupFiles lib_dir filepaths
|
let groups = groupFiles lib_dir filepaths
|
||||||
@@ -66,6 +68,13 @@ parallelBatchCompile jobs opts rootfiles0 =
|
|||||||
dropSlash ('\\':p) = p
|
dropSlash ('\\':p) = p
|
||||||
dropSlash p = p
|
dropSlash p = p
|
||||||
|
|
||||||
|
setJobs opt_n =
|
||||||
|
do ok <- setNumCapabilities opt_n
|
||||||
|
when (not ok) $
|
||||||
|
ePutStrLn $ "To set the number of concurrent threads"
|
||||||
|
++" you need to use +RTS -N"++maybe "" show opt_n
|
||||||
|
++"\n or recompile GF with ghc>=7.6"
|
||||||
|
|
||||||
batchCompile1 lib_dir (opts,filepaths) =
|
batchCompile1 lib_dir (opts,filepaths) =
|
||||||
do cwd <- D.getCurrentDirectory
|
do cwd <- D.getCurrentDirectory
|
||||||
let rel = relativeTo lib_dir cwd
|
let rel = relativeTo lib_dir cwd
|
||||||
|
|||||||
33
src/compiler/GF/System/Concurrency.hs
Normal file
33
src/compiler/GF/System/Concurrency.hs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{-# LANGUAGE CPP,ForeignFunctionInterface #-}
|
||||||
|
-- | A variant of 'Control.Concurrent.setNumCapabilities' that automatically
|
||||||
|
-- detects the number of processors in the system, and is available
|
||||||
|
-- even when compiling with GHC<7.6.
|
||||||
|
module GF.System.Concurrency(
|
||||||
|
-- * Controlling parallelism
|
||||||
|
setNumCapabilities,getNumberOfProcessors) where
|
||||||
|
import qualified Control.Concurrent as C
|
||||||
|
import Foreign.C.Types(CInt(..))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- | Set parallelism to a given number, or use the number of processors.
|
||||||
|
-- Returns 'False' if compiled with GHC<7.6 and the desired number of threads
|
||||||
|
-- hasn't already been set with @+RTS -N/n/ -RTS@.
|
||||||
|
setNumCapabilities opt_n =
|
||||||
|
do n <- maybe getNumberOfProcessors return opt_n
|
||||||
|
#if MIN_VERSION_base(4,6,0)
|
||||||
|
C.setNumCapabilities n
|
||||||
|
return True
|
||||||
|
#else
|
||||||
|
n_now <- C.getNumCapabilities
|
||||||
|
print (n,n_now)
|
||||||
|
return (n==n_now)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-- | Returns the number of processors in the system.
|
||||||
|
getNumberOfProcessors = fmap fromEnum c_getNumberOfProcessors
|
||||||
|
|
||||||
|
-- | According to comments in cabal-install cbits/getnumprocessors.c
|
||||||
|
-- this function is part of the RTS of GHC>=6.12.
|
||||||
|
foreign import ccall "getNumberOfProcessors" c_getNumberOfProcessors :: IO CInt
|
||||||
Reference in New Issue
Block a user