GH-47769: [C++] SVE dynamic dispatch#49756
Conversation
|
Thanks for opening a pull request! If this is not a minor PR. Could you open an issue for this pull request on GitHub? https://github.com/apache/arrow/issues/new/choose Opening GitHub issues ahead of time contributes to the Openness of the Apache Arrow project. Then could you also rename the pull request title in the following format? or See also: |
|
|
2925550 to
ff8566b
Compare
pitrou
left a comment
There was a problem hiding this comment.
Thanks for doing this! Here are a number of comments, questions, and suggestions.
| @@ -17,8 +17,10 @@ | |||
|
|
|||
| #if defined(ARROW_HAVE_NEON) | |||
| # define UNPACK_PLATFORM unpack_neon | |||
There was a problem hiding this comment.
Can we just include bpacking_simd_internal.h and reuse the UNPACK_ARCH128 macro?
There was a problem hiding this comment.
Possibly, though I thought it best that the macro is #undef at the end of the header (making it useless here).
We can make it more explicit (ARROW_BPACKING_UNPACK_ARCH128) an not undefining it.
| #if defined(ARROW_HAVE_NEON) | ||
| # define UNPACK_ARCH128 unpack_neon | ||
| #elif defined(ARROW_HAVE_SSE4_2) | ||
| # define UNPACK_ARCH128 unpack_sse4_2 | ||
| #endif |
There was a problem hiding this comment.
Relying on ARROW_HAVE_NEON etc. is why we need the "128 alt" case, right?
Perhaps we can also depend on which target the file is being compiled for.
For example we could have:
macro(append_runtime_sve128_src SRCS SRC)
if(ARROW_HAVE_RUNTIME_SVE128)
list(APPEND ${SRCS} ${SRC})
set_source_files_properties(${SRC}
PROPERTIES COMPILE_OPTIONS "${ARROW_SVE128_FLAGS}"
COMPILE_DEFINITIONS
"ARROW_COMPILING_FOR_SVE128")
endif()
endmacro()and then:
#if defined(ARROW_COMPILING_FOR_SVE128)
# define UNPACK_ARCH128 unpack_sve128
#elif defined(ARROW_HAVE_NEON)
# define UNPACK_ARCH128 unpack_neon
#elif defined(ARROW_HAVE_SSE4_2)
# define UNPACK_ARCH128 unpack_sse4_2
#endifThere was a problem hiding this comment.
The issue is we need the file compiled twice in ARM (Neon + sve128).
I think it is not possible directly in CMake. The solution is copy to build tree then compile each with different flags.
Is a CMake-only solution satisfactory?
There was a problem hiding this comment.
The issue is we need the file compiled twice in ARM (Neon + sve128).
I think it is not possible directly in CMake.
The easy workaround is to have the same .h file included in two different stub .cc files.
For example have bpacking_simd128_internal.h included by both bpacking_neon.cc and bpacking_sve128.cc.
|
@pitrou I definitely agree with the duplication of the different files, it's pretty tedious. |
ff8566b to
23dc5f0
Compare
|
Something isn't quite right on ARM64 Ubuntu and ARM64 macOS. |
| return dispatch.func(in, out, opts); | ||
| #endif | ||
| auto constexpr kImplementations = UnpackDynamicFunction<Uint>::implementations(); | ||
| if constexpr (kImplementations.size() == 1) { |
There was a problem hiding this comment.
Is this condition actually useful? I guess it's a shortcut, but it's not obvious that it applies to common cases (x86 or ARM with default SIMD options).
At worse, this could be added generically to DynamicDispatch instead. But I doubt it's worth it.
There was a problem hiding this comment.
It is worth it to avoid additional #ifdef, for instance on Macos there is only neon and no SVE (no need to dyn dispatch).
Previously we'd exclude the Neon version from the dynamic dispatch and go #ifdef ARROW_HAVE_NEON then go straight to Neon implementation.
At worse, this could be added generically to
DynamicDispatchinstead. But I doubt it's worth it.
Actually done in GH-49840 so either way here (we'd need to adapt the PR that is not merged first).
There was a problem hiding this comment.
Actually done in GH-49840 so either way here
That PR might prove difficult to adapt for all the lousy compilers we have to support, so I'd rather focus on this one first :)
23dc5f0 to
a8f0ddf
Compare
a8f0ddf to
80e0ab2
Compare
| ->ArgsProduct(kBitWidthsNumValues64); | ||
| #endif | ||
|
|
||
| #if defined(ARROW_HAVE_RUNTIME_SVE128) |
There was a problem hiding this comment.
I wonder if there's an easy way to reduce the duplication we're doing for each runtime SIMD level?
For example if we could write something like:
BENCHMARK_SIMD_UNPACK(Bool, bool, SVE128, Sve128, sve128);and it would expand to:
BENCHMARK_CAPTURE(BM_UnpackBool, Sve128Unaligned, false, &bpacking::unpack_sve128<bool>,
!CpuInfo::GetInstance()->IsSupported(CpuInfo::SVE128),
"Sve128 not available")
->ArgsProduct(kBitWidthsNumValues<bool>);There was a problem hiding this comment.
You mean with a macro?
|
@AntoinePrv Is it possible to run some ARM benchmarks and paste the results somewhere once you're satisfied with the PR? |
Co-authored-by: Antoine Pitrou <pitrou@free.fr>
Co-authored-by: Antoine Pitrou <pitrou@free.fr>
|
@pitrou here are some benchmarks in the [0, 500] num of integer to unpack that Arrow is operating over.
As before, we can sometimes be much penalized by small sizes. |
Perhaps because of larger vectors and a slow epilogue? |
|
But it's impressive that SVE128 is always significantly better than NEON. That's rather good news, given that most SVE implementations have 128-bit vectors. @cyb70289 |
|
@ursabot please benchmark |
|
Benchmark runs are scheduled for commit cbf526f. Watch https://buildkite.com/apache-arrow and https://conbench.arrow-dev.org for updates. A comment will be posted here when the runs are complete. |
|
Silly me, I started the continuous benchmarking suite but our ARM platform there (arm64-t4g-2xlarge) uses Graviton 2 CPUs which don't support SVE. |
|
Thanks for your patience. Conbench analyzed the 2 benchmarking runs that have been run so far on PR commit cbf526f. There were 14 benchmark results indicating a performance regression:
The full Conbench report has more details. |
Interesting. It should not happen if both using equivalent simd operations. Benchmark Neon hotspot shows load_val_as is not inlined No such issue in sve128 code path |
|
That is interesting, I was also investigating a |
Rationale for this change
Just like we dynamically dispatch to AVX2 on x86 CPUs, we want to dynamically dispatch to more advanced SIMD extension on ARM64 chips.
What changes are included in this PR?
Are these changes tested?
Are there any user-facing changes?
No.