#4652: [with code, needs testing] make distutils compile Cython extensions in
parallel
------------------------+---------------------------------------------------
Reporter: craigcitro | Owner: craigcitro
Type: defect | Status: new
Priority: major | Milestone: sage-3.2.2
Component: build | Resolution:
Keywords: |
------------------------+---------------------------------------------------
Comment (by was):
Just out of curiosity, did you try to get this to work without modifying
build_ext.py at all, but by simply changing stuff in that module at
runtime, like I illustrate in #3765?
Here's the diff of what you did:
{{{
--- build_ext.py.orig 2008-11-29 10:32:57.000000000 -0800
+++ build_ext.py 2008-11-29 03:38:35.000000000 -0800
@@ -409,13 +409,57 @@
# get_outputs ()
def build_extensions(self):
+
# First, sanity-check the 'extensions' list
self.check_extensions_list(self.extensions)
- for ext in self.extensions:
- self.build_extension(ext)
+ if not os.environ.has_key('MAKE'):
+ ncpus = 1
+ else:
+ MAKE = os.environ['MAKE']
+ z = [w[2:] for w in MAKE.split() if w.startswith('-j')]
+ if len(z) == 0: # no command line option
+ ncpus = 1
+ else:
+ # Determine number of cpus from command line argument.
+ # Also, use the OS to cap the number of cpus, in case
+ # user annoyingly makes a typo and asks to use 10000
+ # cpus at once.
+ try:
+ ncpus = int(z[0])
+ n = 2*number_of_cpus()
+ if n: # prevent dumb typos.
+ ncpus = min(ncpus, n)
+ except ValueError:
+ ncpus = 1
+
+ import time
+ t = time.time()
+
+ # See if we're trying out the experimental parallel build
+ # code.
+ if ncpus > 1 and os.environ.has_key('SAGE_PARALLEL_DIST'):
+ extensions_to_compile = []
+ for ext in self.extensions:
+ need_to_compile, p = self.prepare_extension(ext)
+ if need_to_compile:
+ extensions_to_compile.append(p)
+
+ if extensions_to_compile:
+ from processing import Pool
+ p = Pool(min(ncpus, len(extensions_to_compile)))
+ for r in p.imap(self.build_extension,
extensions_to_compile):
+ pass
+
+ else:
+ for ext in self.extensions:
+ need_to_compile, p = self.prepare_extension(ext)
+ if need_to_compile:
+ self.build_extension(p)
+
+ print "Total time spent compiling C/C++ extensions: ",
time.time() - t, "seconds."
- def build_extension(self, ext):
+ def prepare_extension(self, ext):
sources = ext.sources
if sources is None or type(sources) not in (ListType, TupleType):
raise DistutilsSetupError, \
@@ -443,9 +487,16 @@
depends = sources + ext.depends
if not (self.force or newer_group(depends, ext_filename,
'newer')):
log.debug("skipping '%s' extension (up-to-date)", ext.name)
- return
+ need_to_compile = False
else:
log.info("building '%s' extension", ext.name)
+ need_to_compile = True
+
+ return need_to_compile, (sources, ext, ext_filename)
+
+ def build_extension(self, p):
+
+ sources, ext, ext_filename = p
# First, scan the sources for SWIG definition files (.i), run
# SWIG on 'em to create .c files, and modify the sources list
@@ -715,3 +766,23 @@
return ext.libraries
# class build_ext
+
+
+
+def number_of_cpus():
+ """
+ Try to determine the number of cpu's on this system.
+ If successful return that number. Otherwise return 0
+ to indicate failure.
+
+ OUTPUT:
+ int
+ """
+ if hasattr(os, "sysconf") and
os.sysconf_names.has_key("SC_NPROCESSORS_ONLN"): # Linux and Unix
+ n = os.sysconf("SC_NPROCESSORS_ONLN")
+ if isinstance(n, int) and n > 0:
+ return n
+ try:
+ return int(os.popen2("sysctl -n hw.ncpu")[1].read().strip())
+ except:
+ return 0
}}}
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/4652#comment:1>
Sage <http://sagemath.org/>
Sage - Open Source Mathematical Software: Building the Car Instead of
Reinventing the Wheel
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en
-~----------~----~----~----~------~----~------~--~---