Thanks to visit codestin.com
Credit goes to github.com

Skip to content

MAINT, Benchmark: print the supported CPU features during the run of performance tests #17737

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

Merged
merged 2 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions benchmarks/benchmarks/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,53 @@
from . import common
import sys
import os

def show_cpu_features():
from numpy.lib.utils import _opt_info
info = _opt_info()
info = "NumPy CPU features: " + (info if info else 'nothing enabled')
# ASV wrapping stdout & stderr, so we assume having a tty here
if 'SHELL' in os.environ and sys.platform != 'win32':
# to avoid the red color that imposed by ASV
print(f"\033[33m{info}\033[0m")
else:
print(info)

def dirty_lock(lock_name, lock_on_count=1):
# this lock occurred before each round to avoid duplicate printing
if not hasattr(os, "getppid"):
return False
ppid = os.getppid()
if not ppid or ppid == os.getpid():
# not sure if this gonna happen, but ASV run each round in
# a separate process so the lock should be based on the parent
# process id only
return False
lock_path = os.path.abspath(os.path.join(
os.path.dirname(__file__), "..", "env", lock_name)
)
# ASV load the 'benchmark_dir' to discovering the available benchmarks
# the issue here is ASV doesn't capture any strings from stdout or stderr
# during this stage so we escape it and lock on the second increment
try:
with open(lock_path, 'a+') as f:
f.seek(0)
count, _ppid = (f.read().split() + [0, 0])[:2]
count, _ppid = int(count), int(_ppid)
if _ppid == ppid:
if count >= lock_on_count:
return True
count += 1
else:
count = 0
f.seek(0)
f.truncate()
f.write(f"{str(count)} {str(ppid)}")
except IOError:
pass
return False


# FIXME: there's no official way to provide extra information to the test log
if not dirty_lock("print_cpu_features.lock"):
show_cpu_features()
16 changes: 2 additions & 14 deletions numpy/_pytesttester.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,13 @@


def _show_numpy_info():
from numpy.core._multiarray_umath import (
__cpu_features__, __cpu_baseline__, __cpu_dispatch__
)
import numpy as np

print("NumPy version %s" % np.__version__)
relaxed_strides = np.ones((10, 1), order="C").flags.f_contiguous
print("NumPy relaxed strides checking option:", relaxed_strides)

if len(__cpu_baseline__) == 0 and len(__cpu_dispatch__) == 0:
enabled_features = "nothing enabled"
else:
enabled_features = ' '.join(__cpu_baseline__)
for feature in __cpu_dispatch__:
if __cpu_features__[feature]:
enabled_features += " %s*" % feature
else:
enabled_features += " %s?" % feature
print("NumPy CPU features:", enabled_features)
info = np.lib.utils._opt_info()
print("NumPy CPU features: ", (info if info else 'nothing enabled'))



Expand Down
44 changes: 35 additions & 9 deletions numpy/lib/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,28 +197,28 @@ def deprecate(*args, **kwargs):
def deprecate_with_doc(msg):
"""
Deprecates a function and includes the deprecation in its docstring.
This function is used as a decorator. It returns an object that can be
used to issue a DeprecationWarning, by passing the to-be decorated
function as argument, this adds warning to the to-be decorated function's

This function is used as a decorator. It returns an object that can be
used to issue a DeprecationWarning, by passing the to-be decorated
function as argument, this adds warning to the to-be decorated function's
docstring and returns the new function object.

See Also
--------
deprecate : Decorate a function such that it issues a `DeprecationWarning`
deprecate : Decorate a function such that it issues a `DeprecationWarning`

Parameters
----------
msg : str
Additional explanation of the deprecation. Displayed in the
Additional explanation of the deprecation. Displayed in the
docstring after the warning.

Returns
-------
obj : object

"""
return _Deprecate(message=msg)
return _Deprecate(message=msg)


#--------------------------------------------
Expand Down Expand Up @@ -1042,4 +1042,30 @@ def _median_nancheck(data, result, axis, out):
result[n] = np.nan
return result

def _opt_info():
"""
Returns a string contains the supported CPU features by the current build.

The string format can be explained as follows:
- dispatched features that are supported by the running machine
end with `*`.
- dispatched features that are "not" supported by the running machine
end with `?`.
- remained features are representing the baseline.
"""
from numpy.core._multiarray_umath import (
__cpu_features__, __cpu_baseline__, __cpu_dispatch__
)

if len(__cpu_baseline__) == 0 and len(__cpu_dispatch__) == 0:
return ''

enabled_features = ' '.join(__cpu_baseline__)
for feature in __cpu_dispatch__:
if __cpu_features__[feature]:
enabled_features += f" {feature}*"
else:
enabled_features += f" {feature}?"

return enabled_features
#-----------------------------------------------------------------------------