Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler search uses a pool of workers #10190

Merged

Conversation

alalazo
Copy link
Member

@alalazo alalazo commented Dec 24, 2018

closes #10127

Following the request in #10127 (review) I started refactoring the logic underneath:

$ spack compiler add

The version in this PR shows much better performance than the version in develop. The main modifications are:

  1. spack.compilers.find_compilers employs a multiprocess.pool.ThreadPool to execute system commands for the detection of compiler versions.
  2. A few memoized functions have been introduced to avoid poking the filesystem multiple times for the same results.

Timing tests will be posted in the discussion below.

@alalazo
Copy link
Member Author

alalazo commented Dec 24, 2018

Local workstation (Ubuntu 18.04 - SSD local filesystem)

With a1565f1:

<this branch>$ time spack compiler add
==> Added 3 new compilers to /home/mculpo/.spack/linux/compilers.yaml
    gcc@8.2.0  gcc@7.3.0  clang@6.0.1-svn334776-1~exp1~20181018152737.116
==> Compilers are defined in the following files:
    /home/mculpo/.spack/linux/compilers.yaml

real    0m0,808s
user    0m0,910s
sys     0m0,289s

while using develop at ec2c5e5:

<develop>$ time spack compiler add
==> Added 3 new compilers to /home/mculpo/.spack/linux/compilers.yaml
    gcc@8.2.0  gcc@7.3.0  clang@6.0.1-svn334776-1~exp1~20181018152737.116
==> Compilers are defined in the following files:
    /home/mculpo/.spack/linux/compilers.yaml

real    0m1,508s
user    0m3,755s
sys     0m0,718s

Fidis front-end (rhel 7.3 - GPFS filesystem)
With a1565f1:

<this-branch>$ time spack compiler add
==> Added 1 new compiler to /home/culpo/.spack/linux/compilers.yaml
    gcc@4.8.5
==> Compilers are defined in the following files:
    /home/culpo/.spack/linux/compilers.yaml

real	0m0.611s
user	0m0.432s
sys	0m0.180s

while using develop at ec2c5e5:

<develop>$ time spack compiler add
==> Added 1 new compiler to /home/culpo/.spack/linux/compilers.yaml
    gcc@4.8.5
==> Compilers are defined in the following files:
    /home/culpo/.spack/linux/compilers.yaml

real	0m1.908s
user	0m1.449s
sys	0m0.463s

@alalazo alalazo force-pushed the features/find_compilers_uses_a_pool branch from 02c2cdf to 8b5c342 Compare December 24, 2018 22:03
@alalazo
Copy link
Member Author

alalazo commented Dec 24, 2018

@tgamblin @becker33 I need to check what's going on with Travis (I get an error similar to #10186 but I can't reproduce it locally with python 2.7). Anyhow, the numbers above seem interesting - if you could give me an early feedback whether you like this approach or not I'll proceed fixing the Cray environments.

@alalazo alalazo force-pushed the features/find_compilers_uses_a_pool branch 4 times, most recently from 9d49d2a to fd4e9aa Compare December 25, 2018 20:08
@alalazo alalazo requested review from tgamblin and becker33 December 25, 2018 22:02
@alalazo
Copy link
Member Author

alalazo commented Dec 25, 2018

The tests now pass, even though I had to skip logging some errors for Python 2.6 (see da56be6). The command:

$ spack compiler add

is 2x-3x faster than develop depending on the machine. Looking forward for some early feedback.

@alalazo
Copy link
Member Author

alalazo commented Dec 26, 2018

FYI, while working on this PR I noticed that Python 2.6 and Python 2.7, on develop, throw exceptions in the spawned processes due to unicode strings not being handled correctly. The offending part is this output captured by one of the command we use to detect the version of compilers:

Command exited with status 1:
    '/usr/bin/cc' '-V'
cc: error: unrecognized command line option ‘-V’
cc: fatal error: no input files

where the non ascii characters '\u2018' and '\u2019' are used to report the error. With fd4e9aa I was able to solve the issue for Python 2.7, while I couldn't find a proper solution for Python 2.6 (hence da56be6).

The problem can be trimmed down to the different behavior sys.stdout.write exhibits between the two Python versions:

$ python2.6
Python 2.6.9 (default, Apr 29 2018, 12:56:59) 
[GCC 7.3.0] on linux4
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.write(u'\u2018\n')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2018' in position 0: ordinal not in range(128)

$ python2.7
Python 2.7.15rc1 (default, Nov 12 2018, 14:31:15) 
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout.write(u'\u2018\n')

This essentially means that llnl.util.tty currently can't handle unicode for Python 2.X. I'm not sure if this is worth a bug report or not...

Copy link
Member

@tgamblin tgamblin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alalazo: this looks awesome to me. Especially the performance results.

The only major piece of feedback I have is that it would be nice to use ThreadPool.map() directly, without the execute/invoke stuff. I just think it's easier to read and more familiar to people if you do that. For example, why not do this (or similar with a function):
python tp.map(lambda args: f(*args), arguments)

instead of flipping it around with execute()?

  1. As kind of indicated above, I think it would be better if we made it so that the mapped functions don't take callback arguments, because I see that as more portable to a multiprocess pool if it ever makes sense to use one.

More details in comments. See what you think.

lib/spack/llnl/util/filesystem.py Outdated Show resolved Hide resolved
lib/spack/spack/compiler.py Outdated Show resolved Hide resolved
lib/spack/llnl/util/multiproc.py Show resolved Hide resolved
lib/spack/llnl/util/multiproc.py Outdated Show resolved Hide resolved
lib/spack/llnl/util/multiproc.py Outdated Show resolved Hide resolved
lib/spack/spack/compiler.py Outdated Show resolved Hide resolved
lib/spack/spack/compiler.py Outdated Show resolved Hide resolved
lib/spack/spack/compilers/__init__.py Outdated Show resolved Hide resolved
lib/spack/spack/compiler.py Outdated Show resolved Hide resolved
lib/spack/spack/compiler.py Outdated Show resolved Hide resolved
@alalazo alalazo force-pushed the features/find_compilers_uses_a_pool branch from da56be6 to e72f8eb Compare January 7, 2019 13:48
@alalazo
Copy link
Member Author

alalazo commented Jan 10, 2019

@tgamblin If the code in spack/compilers/__init__.py looks good enough I'll proceed restoring the two unit tests under FIXME and porting the Cray part. In case, let me know if the code needs further explanations in the comments or docstrings.

@alalazo alalazo force-pushed the features/find_compilers_uses_a_pool branch from 5448ef0 to e8133ea Compare January 18, 2019 14:52
@alalazo alalazo force-pushed the features/find_compilers_uses_a_pool branch 3 times, most recently from 55d88a0 to 61368e2 Compare February 7, 2019 18:57
@alalazo
Copy link
Member Author

alalazo commented Feb 8, 2019

Real time reported for compiler detection as of 397cdf3:

PR Ubuntu 18.04 (SSD ext4) CentOS 7.3 (GPFS) Cray (Piz Daint)
Before this PR 0m1,442s 0m1.862s 0m1.577s
After this PR 0m0,680s 0m0.650s 0m1.520s

Summary: the time to detect compilers for usual linux systems improved substantially, Cray remained quite the same (not surprising as the main optimizations were on avoiding useless os.stat and the Cray detection system is based modules instead of on file searching).

alalazo added 15 commits June 7, 2019 09:30
This is to be consistent with the 'can_access' function already present
in the module.
* Simplified _CompilerID

* Extracted search_compiler_commands from Compiler

* Added search_regexps to Compiler

* A few functions manipulating paths that could be useful in other
  parts of the code have been moved to llnl.util.filesystem

* Removed deferred functions in favor of mapping arguments to
  functions as required in the review

* Moved most of the code involved in compiler detection in
  spack.compilers
This permits to deal more neatly with peculiarities of Cray systems when
detecting compilers.
The function doesn't use anymore 'map', 'filter' and 'os.path.realpath'
 + it's based on a single loop.
@alalazo alalazo force-pushed the features/find_compilers_uses_a_pool branch 2 times, most recently from 1237a14 to ea7910a Compare June 7, 2019 08:08
@alalazo
Copy link
Member Author

alalazo commented Jun 7, 2019

Ready for further review!

@tgamblin tgamblin merged commit 6d56d45 into spack:develop Jun 7, 2019
@alalazo alalazo deleted the features/find_compilers_uses_a_pool branch June 7, 2019 19:30
for o in oss:
compiler_lists.extend(o.find_compilers(*paths))
return compiler_lists
if path_hints is None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alalazo I think this check might be overly strict. I'm seeing cases where path_hints is [] for spack compiler find (which I expect would check PATH) and so this check is not triggered.

carsonwoods pushed a commit to carsonwoods/spack that referenced this pull request Jun 27, 2019
- spack.compilers.find_compilers now uses a multiprocess.pool.ThreadPool to execute
  system commands for the detection of compiler versions.

- A few memoized functions have been introduced to avoid poking the filesystem multiple
  times for the same results.

- Performance is much improved, and Spack no longer fork-bombs the system when doing a `compiler find`
dev-zero pushed a commit to dev-zero/spack that referenced this pull request Aug 13, 2019
- spack.compilers.find_compilers now uses a multiprocess.pool.ThreadPool to execute
  system commands for the detection of compiler versions.

- A few memoized functions have been introduced to avoid poking the filesystem multiple
  times for the same results.

- Performance is much improved, and Spack no longer fork-bombs the system when doing a `compiler find`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants