Skip to content

WIP: Needs validation of changes - #9553

Closed
MGN-GIT wants to merge 1 commit into
CGAL:mainfrom
MGN-GIT:aarch64
Closed

WIP: Needs validation of changes #9553
MGN-GIT wants to merge 1 commit into
CGAL:mainfrom
MGN-GIT:aarch64

Conversation

@MGN-GIT

@MGN-GIT MGN-GIT commented Jul 5, 2026

Copy link
Copy Markdown

Summary of Changes

  • The PR adds support for SIMD optimizations for CGAL library for AARCH64 systems
  • Improves low-level numeric predicates and interval arithmetic for CGAL on AARCH64 systems

Release Management

  • Affected package(s):
  • Issue(s) solved (if any): fix #0000, fix #0000,...
  • Feature/Small Feature (if any): SIMD feature for AARCH64
  • Link to compiled documentation (obligatory for small feature) wrong link name to be changed
  • License and copyright ownership:

@MGN-GIT MGN-GIT changed the title Aarch64 Introduce SIMD optimization for AARCH64 Jul 5, 2026

@mglisse mglisse left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Any word on benchmark results?

Comment on lines +348 to +354
#ifdef CGAL_USE_SSE2_MAX
CGAL::Max<double> mmax;

maxx = mmax(maxx, aprx, apsx);
maxy = mmax(maxy, apry, apsy);
maxz = mmax(maxz, aprz, apsz);
#elif defined CGAL_USE_NEON_MAX

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
#ifdef CGAL_USE_SSE2_MAX
CGAL::Max<double> mmax;
maxx = mmax(maxx, aprx, apsx);
maxy = mmax(maxy, apry, apsy);
maxz = mmax(maxz, aprz, apsz);
#elif defined CGAL_USE_NEON_MAX
#if defined CGAL_USE_SSE2_MAX || defined CGAL_USE_NEON_MAX

to reduce duplication? It might even make sense to introduce a common macro for both, if they are always used together.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the suggestion @mglisse , I have added a common macro and simplified the simd logic.

Comment on lines +381 to +385
sse2minmax(maxx,maxy,maxz);
// maxy can contain ANY element
#endif
#elif defined CGAL_USE_NEON_MAX
neon_minmax(maxx,maxy,maxz);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If sse2minmax and neon_minmax work the same way, it could help reduce duplication to give them the same name (no opinion on what that name should be).
We could even introduce a helper function (with sort3 in its name?), defined for all platforms, to avoid repeating the whole block of code.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yes, thanks for the suggestions

#include <CGAL/sse2.h>
#endif

#ifdef CGAL_USE_NEON_FABS

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this macro automatically defined somewhere, or for now a user has to define it by hand?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@mglisse
These macros should passed by users while building while using CGAL headers.

Comment thread Number_types/include/CGAL/double.h Outdated
#ifdef CGAL_USE_NEON_FABS
inline double neon_fabs(double a)
{
return vget_lane_f64(vabs_f64(vdup_n_f64(a)), 0);;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this again specifically for visual studio, while all other compilers do ok with normal code?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I have been testing this code changes with github windows arm64 runners, so I have made changes with respect to MSVC. MSVC does not support direct NEON simd for double abs. But GNU and Clang-like compilers supports direct NEON double abs.

#if defined __GNUG__ || defined __clang__
// The "+w" constraint pins the value in a NEON/FP register and acts as
// a compiler barrier without emitting any instruction.
asm volatile ("" : "+w"(x));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No "+mw" for gcc?
(I haven't played with these things for a while, so I don't know how compilers have evolved since then)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

GCC uses "w" for Floating point register for AARCH64 family. Refer: https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html

Comment on lines +314 to +315
volatile float64x2_t e = x;
std::memcpy(&x, (void*)&e, 16);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤞 that this still works...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I tested this with sample code with compiler explorer. MSVC and GCC produce identical results. The MSVC fallback emits a real memory store/load, matching GCC's behavior for the volatile-copy implementation.

Comment thread Number_types/include/CGAL/FPU.h Outdated
Comment on lines +423 to +425
// MSVC on ARM64: must come first, before CGAL_SAFE_SSE2 and the plain
// _MSC_VER branch, because _controlfp_s and _MM_SET_ROUNDING_MODE are
// both x86-only and do not exist on ARM64.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe the "plain" _MSC_VER branch should be fixed to test architecture macros at the same time?
Also, why before CGAL_SAFE_SSE2, is that defined for arm as well now?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The rounding-mode ladder below must test _MSC_VER && _M_ARM64 FIRST,before CGAL_SAFE_SSE2 and before the plain _MSC_VER branch, for two reasons:

  1. CGAL_SAFE_SSE2 can be defined on MSVC ARM64 if the compiler sets
    FLT_EVAL_METHOD==0 (which it does), causing _MM_SET_ROUNDING_MODE
    to be selected — but that SSE2 intrinsic does not exist on ARM64.
  2. The plain _MSC_VER branch uses _controlfp_s, which is also x86-only
    and absent on ARM64.

The plain _MSC_VER branch is also guarded with !defined(_M_ARM64) below
to make the intent explicit and prevent future regressions.

@MGN-GIT
MGN-GIT requested a review from mglisse July 5, 2026 13:49
@MGN-GIT

MGN-GIT commented Jul 5, 2026

Copy link
Copy Markdown
Author

Any word on benchmark results?

I was trying to build CGAL benchmarks, but I am hitting lot of errors while building benchmarks.

@MGN-GIT

MGN-GIT commented Jul 5, 2026

Copy link
Copy Markdown
Author

Hi @mglisse
Just following up on the benchmarks, I have written a custom benchmark code to test the affected functions. Please find the results below:

Layer Operation Scalar (ns/op) NEON (ns/op) % Improvement
Interval_nt add (a+b) 0.82 0.80 2.4%
Interval_nt sub (a-b) 1.22 1.22 0.0%
Interval_nt mul (a*b) 2.81 2.83 -0.7%
Interval_nt div (a/b) 0.85 0.87 -2.4%
Interval_nt sqrt(b) 2.49 2.50 -0.4%
Interval_nt square(b) 1.21 1.23 -1.7%
Interval_nt abs(a) 0.30 0.25 16.7%
Interval_nt min(a,b) 0.29 0.25 13.8%
Interval_nt max(a,b) 0.30 0.25 16.7%
Interval_nt ia*double 6.52 5.78 11.3%
Interval_nt double*ia 5.80 5.77 0.5%
Interval_nt ia/double 6.55 6.55 0.0%
Interval_nt double/ia 0.50 0.50 0.0%
Interval_nt negate (-a) 0.25 0.25 0.0%
Interval_nt is_same 0.25 0.25 0.0%
Interval_nt do_overlap 0.25 0.25 0.0%
StaticFilter orientation_3 5.50 5.00 9.1%
StaticFilter side_of_oriented_sphere_3 10.90 10.20 6.4%
StaticFilter orientation_3 (near-degen) 5.60 4.90 12.5%
Delaunay3 insert 200000 pts ×10 4179.00 2820.50 32.5%
Delaunay3 insert 1000000 pts ×4 4456.00 2920.50 34.5%
Delaunay3 insert 2000000 pts ×2 4659.25 2943.25 36.8%

@afabri

afabri commented Jul 5, 2026

Copy link
Copy Markdown
Member

Just following up on the benchmarks, I have written a custom benchmark code to test the affected functions. Please find the results below:

Please commit your benchmark code.
In #9546 I added https://github.com/CGAL/cgal/pull/9546/changes#diff-d8aedcc72049e5592d5b89e7cc315747079bfbded4494a051cd99fa9194da24e

@MGN-GIT
MGN-GIT marked this pull request as draft July 6, 2026 02:51
@MGN-GIT MGN-GIT closed this Jul 6, 2026
@MGN-GIT MGN-GIT changed the title Introduce SIMD optimization for AARCH64 WIP: Needs validation of changes Jul 6, 2026
@MGN-GIT MGN-GIT reopened this Jul 6, 2026
@MGN-GIT MGN-GIT closed this Jul 6, 2026
@MGN-GIT
MGN-GIT deleted the aarch64 branch July 6, 2026 05:59
@MGN-GIT
MGN-GIT restored the aarch64 branch July 6, 2026 05:59
@MGN-GIT MGN-GIT reopened this Jul 6, 2026
@MGN-GIT MGN-GIT closed this Jul 6, 2026
@MGN-GIT
MGN-GIT deleted the aarch64 branch July 6, 2026 06:03
@MGN-GIT

MGN-GIT commented Jul 6, 2026

Copy link
Copy Markdown
Author

Hi @afabri
There are some issues with build on AARCH64, I would like to open a separate PR with new set of changes and benchmark workloads. Sorry for the inconvience,
Thanks

Sign up for free to 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