# Copyright (C) 2015 Joshua Willis
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
This module defines optimization flags and some optimized utilities.
"""
import os, sys
import logging
from collections import OrderedDict
logger = logging.getLogger('pycbc.opt')
[docs]
def get_l2_cache_size():
"""
Get the L2 cache size from the environment variable _PYCBC_L2_CACHE_SIZE.
Returns
-------
int or None
The L2 cache size in bytes if the environment variable is set, None otherwise.
"""
cache_size_str = os.environ.get("_PYCBC_L2_CACHE_SIZE", None)
if cache_size_str is not None:
return int(cache_size_str)
return None
[docs]
def insert_optimization_option_group(parser):
"""
Adds the options used to specify optimization-specific options.
Parameters
----------
parser : object
OptionParser instance
"""
optimization_group = parser.add_argument_group("Options for selecting "
"optimization-specific settings")
optimization_group.add_argument("--cpu-affinity", help="""
A set of CPUs on which to run, specified in a format suitable
to pass to taskset.""")
optimization_group.add_argument("--cpu-affinity-from-env", help="""
The name of an enivornment variable containing a set
of CPUs on which to run, specified in a format suitable
to pass to taskset.""")
[docs]
def verify_optimization_options(opt, parser):
"""Parses the CLI options, verifies that they are consistent and
reasonable, and acts on them if they are
Parameters
----------
opt : object
Result of parsing the CLI with OptionParser, or any object with the
required attributes
parser : object
OptionParser instance.
"""
# Pin to specified CPUs if requested
requested_cpus = None
if opt.cpu_affinity_from_env is not None:
if opt.cpu_affinity is not None:
logger.error(
"Both --cpu_affinity_from_env and --cpu_affinity specified"
)
sys.exit(1)
requested_cpus = os.environ.get(opt.cpu_affinity_from_env)
if requested_cpus is None:
logger.error(
"CPU affinity requested from environment variable %s "
"but this variable is not defined",
opt.cpu_affinity_from_env
)
sys.exit(1)
if requested_cpus == '':
logger.error(
"CPU affinity requested from environment variable %s "
"but this variable is empty",
opt.cpu_affinity_from_env
)
sys.exit(1)
if requested_cpus is None:
requested_cpus = opt.cpu_affinity
if requested_cpus is not None:
command = 'taskset -pc %s %d' % (requested_cpus, os.getpid())
retcode = os.system(command)
if retcode != 0:
logger.error(
'taskset command <%s> failed with return code %d',
command, retcode
)
sys.exit(1)
logger.info("Pinned to CPUs %s ", requested_cpus)
[docs]
class LimitedSizeDict(OrderedDict):
""" Fixed sized dict for FIFO caching"""
def __init__(self, *args, **kwds):
self.size_limit = kwds.pop("size_limit", None)
OrderedDict.__init__(self, *args, **kwds)
self._check_size_limit()
def __setitem__(self, key, value):
OrderedDict.__setitem__(self, key, value)
self._check_size_limit()
def _check_size_limit(self):
if self.size_limit is not None:
while len(self) > self.size_limit:
self.popitem(last=False)