Skip to content

misc: Update advisor with oneAPI 2025 #2533

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 11 commits into from
Mar 7, 2025
Merged

Conversation

georgebisbas
Copy link
Contributor

Some more changes are needed, but finally works

Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

# Locate the Intel Advisor installation and
# add the necessary flags to the compiler
from devito.operator.profiling import locate_intel_advisor
path = locate_intel_advisor()
Copy link
Contributor

Choose a reason for hiding this comment

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

Why aren't all those set by the setvars.sh that's what it's supposed to be for

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, this was true with Intel studios, but now they are not by default. You have to link explicitly. At least, this is what I see.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And this is actually why it stopped working at some point

Copy link

codecov bot commented Feb 10, 2025

Codecov Report

Attention: Patch coverage is 41.66667% with 28 lines in your changes missing coverage. Please review.

Project coverage is 87.55%. Comparing base (e1dcb86) to head (fd5df3f).
Report is 12 commits behind head on master.

Files with missing lines Patch % Lines
devito/operator/profiling.py 31.57% 12 Missing and 1 partial ⚠️
devito/arch/archinfo.py 25.00% 9 Missing ⚠️
tests/test_benchmark.py 40.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2533      +/-   ##
==========================================
+ Coverage   87.52%   87.55%   +0.03%     
==========================================
  Files         238      238              
  Lines       47034    47032       -2     
  Branches     4144     4143       -1     
==========================================
+ Hits        41165    41178      +13     
+ Misses       5176     5161      -15     
  Partials      693      693              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

project = advisor.open_project(str(project))

if not project:
err('Could not open project %s.' % project)
err(f'Could not open project {project}.')
Copy link
Contributor

Choose a reason for hiding this comment

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

What does open_project return if it fails to open the project? This error message might return something cryptic since project gets overwritten

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was sure I had replied in this, not sure I cannot see my message. This is part of the advisor API, it should already be there

https://www.intel.com/content/www/us/en/developer/articles/training/how-to-use-the-intel-advisor-python-api.html

@@ -267,86 +272,6 @@
"As you can see from this roofline graph, the main point is different from the single point of the previous graph. Moreover, each point is labelled with 'Time' and 'Incidence' indicators. These represent the total execution time of each loop's main body and their percentage incidence on the total execution time of the main time loop."
]
},
{
Copy link
Contributor Author

Choose a reason for hiding this comment

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

All this is redundant in my opinion to be treated as-a-worthy to mention API

compiler.add_library_dirs(libdir)
compiler.add_ldflags('-Wl,-rpath,%s' % libdir)
super(AdvisorProfiler, self).__init__(name)
return
Copy link
Contributor

Choose a reason for hiding this comment

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

no need

Copy link
Contributor

Choose a reason for hiding this comment

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

AFAICT, this is just yet another empty constructor? droppable?

@@ -771,6 +771,18 @@ def __init_finalize__(self, **kwargs):
self.__init_intel_mpi__()
self.__init_intel_mpi_flags__()

if configuration['profiling'] == 'advisor':
Copy link
Contributor

Choose a reason for hiding this comment

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

see comment below, but basically since "profiling" requires third-party tools (as opposed to MPI which is an actual API) I have a preference for this bit of logic to be kept in profiling

@georgebisbas georgebisbas force-pushed the advisor_refresh_II branch 3 times, most recently from 4c1f058 to ed910e5 Compare February 14, 2025 07:48
@@ -219,6 +219,12 @@ def _build(cls, expressions, **kwargs):

# Required for the jit-compilation
op._compiler = kwargs['compiler']

# Add any metadata from the profiler
Copy link
Contributor

Choose a reason for hiding this comment

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

nitpicking, I wouldn't call it "metadata"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hope is better

@georgebisbas georgebisbas requested a review from EdCaunt February 14, 2025 08:36
conftest.py Outdated
@@ -80,7 +80,7 @@ def skipif(items, whole_module=False):
skipit = "`icx+cpu64` won't work with this test"
break
# Skip if icx or advisor are not available
if i not in 'only-advisor' or \
if i not in ('noadvisor') or \
Copy link
Contributor

Choose a reason for hiding this comment

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

no this is wrong as it's not a tuple

Copy link
Contributor Author

Choose a reason for hiding this comment

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

omg, forgot the comma

libdir = path.joinpath('lib64').as_posix()
self._lib_dirs = [libdir]
else:
warning("Intel Advisor not found; reverting to `advanced`")
Copy link
Contributor

Choose a reason for hiding this comment

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

is it really reverting?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good catch, indeed it is reverting, but there is another mini-bug. It was reverting to basic, now it is reverting to advanced, and dropped a double-emmited warning due to this

Comment on lines -517 to -518
warning("Couldn't set up `%s` profiler; reverting to `advanced`" % level)
profiler = profiler_registry['basic'](name)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here, it was reverting to basic

Copy link
Contributor

Choose a reason for hiding this comment

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

ok but no need for that extra var imho (nitpicking)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

well this was only for a better fstring...but ok

if path:
self._include_dirs = [path.joinpath('include').as_posix()]
libdir = path.joinpath('lib64').as_posix()
self._lib_dirs = [libdir]
Copy link
Contributor

Choose a reason for hiding this comment

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

no, instances shouldn't change class attributes like that....

and btw why is it even a class attribute ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What should it have been?

Comment on lines -517 to -518
warning("Couldn't set up `%s` profiler; reverting to `advanced`" % level)
profiler = profiler_registry['basic'](name)
Copy link
Contributor

Choose a reason for hiding this comment

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

ok but no need for that extra var imho (nitpicking)

@FabioLuporini FabioLuporini changed the title advisor: Update advisor with oneAPI 2025 misc: Update advisor with oneAPI 2025 Feb 17, 2025

path = get_advisor_path()
if path:
self.add_include_dir(path.joinpath('include').as_posix())
Copy link
Contributor

Choose a reason for hiding this comment

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

as explained above, this should just be self._include_dirs.append(...)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

@georgebisbas georgebisbas force-pushed the advisor_refresh_II branch 2 times, most recently from c6e780d to c700ca2 Compare February 26, 2025 12:53
conftest.py Outdated
@@ -79,6 +79,12 @@ def skipif(items, whole_module=False):
isinstance(configuration['platform'], Cpu64):
skipit = "`icx+cpu64` won't work with this test"
break
# Skip if icx or advisor are not available
if i == 'noadvisor' and \
not isinstance(configuration['compiler'], IntelCompiler) or \
Copy link
Contributor

Choose a reason for hiding this comment

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

this is wrong again, I think, because of and/or operator precedence...

The fact we got this wrong multiple times and nothing breaks on CI suggests it's not very useful maybe

if path:
self._include_dirs.append(path.joinpath('include').as_posix())
self._lib_dirs.append(path.joinpath('lib64').as_posix())
self._attempted_init = True
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe for another day, but these three lines

     self._attempted_init = True
else:
     self._attempted_init = False

could become a single line

self._attempted_init = bool(path)

but anyway, nitpicking... maybe you can do it in another PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

but why append then if path is None? If the compiler reverts to advanced in the case of advisor's absence, the paths will be linked right?

@@ -158,9 +155,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;37;32mOpening project...\u001b[0m\n",
"\u001b[1;37;32mOpening project /home/gb4018/workspace/devitocodes/devito/examples/performance/profilings/JupyterProfiling...\u001b[0m\n",
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not OK, I don't like personal dirs in logs (ie gb4018)

@@ -218,9 +219,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1;37;32mOpening project...\u001b[0m\n",
"\u001b[1;37;32mOpening project /home/gb4018/workspace/devitocodes/devito/examples/performance/profilings/JupyterProfiling...\u001b[0m\n",
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

@@ -219,6 +219,12 @@ def _build(cls, expressions, **kwargs):

# Required for the jit-compilation
op._compiler = kwargs['compiler']

# Required for compilation by the profiler
Copy link
Contributor

Choose a reason for hiding this comment

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

Why aren't those part of the profller init?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was before, and this was the reason it was not working, as a different compiler was build after doing the profiler init. Related discussion here: https://devitocodes.slack.com/archives/C7JMLMSG0/p1739458707616429?thread_ts=1739458681.588539&cid=C7JMLMSG0

Copy link
Contributor

@JDBetteridge JDBetteridge left a comment

Choose a reason for hiding this comment

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

Nitpicks. But otherwise LGTM

# saving the chart in PNG format
plt.savefig('%s.png' % name, bbox_extra_artists=(legend,), bbox_inches='tight')
# saving the chart in PDF format
plt.savefig('%s.pdf' % name, bbox_extra_artists=(legend,), bbox_inches='tight')
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
plt.savefig('%s.pdf' % name, bbox_extra_artists=(legend,), bbox_inches='tight')
plt.savefig(f'{name}.pdf', bbox_extra_artists=(legend,), bbox_inches='tight')

mode. This analysis, together with the `survey` analysis, is necessary to
generate a roofline. Both are run by `run_advisor.py`.
* Requires python3, untested in earlier versions of python and conda environments
* Currently requires download of repository and running `pip3 install .`, the scripts
* Requires Python3, untested in conda environments
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* Requires Python3, untested in conda environments
* Requires Python 3.9 or later, untested in conda environments

Let's not use unsupported Python versions!

figpath = os.path.realpath(__file__).split(os.path.basename(__file__))[0]
log('Figure saved in %s%s.png.' % (figpath, name))
log('\nFigure saved in %s%s.pdf.' % (figpath, name))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
log('\nFigure saved in %s%s.pdf.' % (figpath, name))
log(f'\nFigure saved in {figpath}{name}.pdf.')


# Save the JSON file
with open('%s.json' % name, 'w') as f:
f.write(json.dumps(roofline_data))

log('JSON file saved as %s.json.' % name)
log('\nJSON file saved as %s.json.' % name)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
log('\nJSON file saved as %s.json.' % name)
log(f'\nJSON file saved as {name}.json.')

@FabioLuporini FabioLuporini merged commit b22dd66 into master Mar 7, 2025
31 checks passed
@FabioLuporini FabioLuporini deleted the advisor_refresh_II branch March 7, 2025 08:26
@FabioLuporini
Copy link
Contributor

Merged, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants