Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Implements CVectorExtensionsTarget - #557

Open
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target
Open

Implements CVectorExtensionsTarget#557
kaushikcfd wants to merge 11 commits into
mainfrom
c_vecextensions_target

Conversation

@kaushikcfd

@kaushikcfdkaushikcfd commented Mar 2, 2022

Copy link
Copy Markdown
Collaborator

/cc @sv2518

Adds support for GNU vector extensions.

TODO:

Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

@inducer: Any big red signals with the user-facing interface of specifying fallbacks?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@kaushikcfdkaushikcfdJul 6, 2022

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, this has been restructured.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 5ac2e2e to 3d3c1deCompareMarch 3, 2022 20:37
@kaushikcfd
kaushikcfd marked this pull request as ready for review March 3, 2022 20:38
@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

This is ready for a look, for a better reviewing experience please see the patch on a commit-by-commit basis.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from ad2372f to 5b0f9c2CompareMarch 4, 2022 19:49
@sv2518

sv2518 commented Mar 8, 2022

Copy link
Copy Markdown
Contributor

There are two things which we definitely still need before we are able to fully automate this into the Firedrake/PyOP2 code.

  • The first one is that conditionals cannot be vectorised yet. There is an error in Firedrake with ``pymbolic.mapper.UnsupportedExpressionError: <class 'loopy.expression.VectorizabilityChecker'> cannot handle expressions of type <class 'pymbolic.primitives.If'> An example of a test where we run into that is this one: tests/extrusion/test_mixed_periodic.py::test_mixed_periodic[interval]

--> Fix in PR

  • That math functions are not vectorised is also still missing. We run into an error:
passing '__attribute__((__vector_size__(4 * sizeof(double)))) double' (vector of 4 'double' values) to parameter of incompatible type 'double'
t0[expr_p0] = t0[expr_p0] + 6.283185307179586 * cos(expr_t1); 

An example of a test where we run into that is tests/slate/test_slate_infrastructure.py::test_arguments[dg1-mesh0]

--> Fix in PR

  • Two other I believe faster to fix issues are one that is related to complex types on AVX512. We have an error that looks like the following so I think there is some support missing for complex128. Maybe we should not vectorised for complex in Firedrake?
File "/opt/hostedtoolcache/Python/3.9.10/x64/lib/python3.9/site-packages/loopy/target/c_vector_extensions.py", line 107, in vector_dtype vec.types[base.numpy_dtype, count], KeyError: (dtype('complex128'), 8)

--> This was a bug on our side. Fixed in PyOP2

  • The other one I don’t quite understand but it is a gcc compiler error
error: use of undeclared identifier 'iel_batch'
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start]; I had a look at the C code and I think an iname has been dropped
/* bulk slab for 'iel_outer' */
for (int32_t iel_outer = 1; iel_outer <= -2 + -1 * start + (3 + end + 3 * start) / 4; ++iel_outer)
{
{
int32_t const i4 = 0;
#pragma omp simd
for (int32_t iel_batch = 0; iel_batch <= 3; ++iel_batch)
(t0[0])[iel_batch] = 0.0;
}
/* no-op (insn=inne__start) */
{
int32_t const inne_i = 0;
t0[0] = t0[0] + dat0[4 * iel_outer + iel_batch + start] * dat1[4 * iel_outer + iel_batch + start];
}
...

It looks like the iname for iel_batch was dropped

@sv2518

Copy link
Copy Markdown
Contributor

So I had a look at the code. I think I can fix the first issue by adding a map_if to VectorizabilityChecker that throws a UnvectorizableError(). Does that sound about right?
For the second issue I think we need to check in map_variable if the variable is one of these

func_names = set(["abs_*", "fabs_*", "cos_*", "sin_*", "exp_*", "pow_*",
"sqrt_*", "fmax_*", "fmin_*", "atan2_*", "log_*",
"tanh_*"])

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.
If you agree with that I can write the code to address both.

@kaushikcfd

Copy link
Copy Markdown
CollaboratorAuthor

It looks like the iname for iel_batch was dropped

This looks like a bug in loopy's vectorization implementation, with reductions in them.

(and potentially other supported math functions) and throw a UnvectorizableError() if it is.

I think falling back to omp-simd might make more sense. Looks like that's already being done here:

defmap_call(self, expr):
# FIXME: Should implement better vectorization check for function calls
rec_pars= [
self.rec(child) forchildinexpr.parameters]
ifany(rec_pars):
raiseUnvectorizableError("fucntion calls cannot yet be vectorized")

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b1982b8 to 6ea1c80CompareMarch 11, 2022 18:22
@kaushikcfdkaushikcfd mentioned this pull request Mar 11, 2022
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ea1c80 to 8713fc3CompareMarch 11, 2022 18:46
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 56ab5dc to 6ffe97aCompareApril 1, 2022 05:41
@kaushikcfd
kaushikcfd marked this pull request as draft April 1, 2022 06:20
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 6ffe97a to fa1d552CompareApril 1, 2022 06:23
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 4 times, most recently from 42390e3 to fd4ae30CompareMay 7, 2022 16:35
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 3 times, most recently from 688aa94 to 4c0c013CompareMay 11, 2022 22:53
@kaushikcfd
kaushikcfd marked this pull request as ready for review May 12, 2022 17:09
@kaushikcfd
kaushikcfd requested a review from inducerMay 13, 2022 16:16

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Some initial thoughts from a quick scroll.

assert isinstance(inner, CodeGenerationResult)
if isinstance(inner.current_ast(novec_self),
astb.ast_comment_class):
# loop body is a comment => do not emit the loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is puzzling. Could you explain what leads to this?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

A noop instruction is emitted as a comment.

Comment threadloopy/target/cuda.py
Comment threadloopy/target/c/__init__.py
Comment threadloopy/codegen/control.py Outdated
Comment on lines +128 to +93
elif filter_iname_tags_by_type(tags, OpenMPSIMDTag):
func = generate_openmp_simd_loop

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

As written, I think this is very weird, as OpenMP is clearly target-specific. But the concept of a loop with no dependencies between iterations is universal. So maybe that's what the tag should reflect?

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Yep, agreed. Bleeding OpenMP-specific things into iname tags was an abstraction failure. Restructured to specify the fallback via target attributes.

Comment threadloopy/check.py Outdated
Comment on lines +496 to +616
# do not check for vec-inames as their implementation is accompanied
# with a fallback machinery
par_inames = {iname for iname in dom_inames
if (kernel.iname_tags_of_type(iname, ConcurrentTag)
and not kernel.iname_tags_of_type(iname, VectorizeTag))}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Explain that the fallback is "don't vectorize".

Comment threadloopy/check.py Outdated
Comment threadtest/test_target.py Outdated
Comment on lines +702 to +771
knl = lp.make_kernel(
"{[i, j1, j2, j3]: 0<=i<10 and 0<=j1,j2,j3<4}",
"""
<> temp1[j1] = x[i, j1]
<> temp2[j2] = 2*temp1[j2] + 1 {inames=i:j2}
y[i, j3] = temp2[j3]
""",
[lp.GlobalArg("x, y", shape=lp.auto, dtype=float)],
seq_dependencies=True,
target=lp.CVectorExtensionsTarget(),
lang_version=(2018, 2))

knl = lp.tag_inames(knl, {"j1": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j2": lp.VectorizeTag(lp.OpenMPSIMDTag()),
"j3": lp.VectorizeTag(lp.OpenMPSIMDTag())})

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I think OpenMPSIMDTag shoudl be renamed to something more generic, and then this fallback could be automatic.

@sv2518sv2518 mentioned this pull request May 18, 2022
@sv2518

Copy link
Copy Markdown
Contributor

From the Firedrake side this looks like its good to go. Thanks for all your work on it Kaushik!
We will update our fork as soon as this is merged on your main and then merge the corresponding PyOP2 PR.

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch 6 times, most recently from 3bdd997 to 57e2440CompareJuly 6, 2022 00:47
@kaushikcfd
kaushikcfd requested a review from inducerJuly 6, 2022 00:48
@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from 57e2440 to 47eb2d5CompareJuly 11, 2022 12:28
@sv2518

Copy link
Copy Markdown
Contributor

Some tests in the actions for the automatic vectorisation of Firedrake are currently failing due to the issue I reported in #648

@kaushikcfd
kaushikcfdforce-pushed the c_vecextensions_target branch from b132997 to df179b5CompareOctober 20, 2022 17:01
@sv2518

Copy link
Copy Markdown
Contributor

Hi! I have tested the updated branch together with the updated version of Firedrake and PyOP2 and both CIs are passing. The PRs in both components were already approved and I am not around for long anymore. It would be awesome if you could merge this into Loo.py, so that we can merge it on our side and make vectorisation available to all of our users.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@kaushikcfd@sv2518@inducer