Skip to content

external partons with branch-free helicity#1095

Merged
zeniheisser merged 2 commits into
madgraph5:masterfrom
zeniheisser:helicity_branching
Jul 17, 2026
Merged

external partons with branch-free helicity#1095
zeniheisser merged 2 commits into
madgraph5:masterfrom
zeniheisser:helicity_branching

Conversation

@zeniheisser

Copy link
Copy Markdown
Contributor

Removed if-else blocks for helicity states in external fermions with branch-free arithmetic; always define floating point ip and im denoting whether it has plus or minus polarisation (1.0 if yes, 0.0 if no) and multiply outputs by this number to automatically set correct spinors to zero. (This trick is already done for massive fermions as well as external vector bosons)

Minimal checks to see if this had any measureable performance impact: Running standalone_cudacpp with no SIMD and commenting out everything but the IXXXXX and OXXXXX calls in sigmaKin, there is no difference in evaluation runtime. Using the internal timers for check_cpp.exe with -p and running ~a billion events (./check_cpp.exe 1024 1024 1024):
(Branch-free) 3a SigmaKin : 1.169649 sec
(Original ver) 3a SigmaKin : 1.172651 sec

I ran a couple of times to see, and even running just external fermions there was no measureable runtime difference.

@zeniheisser
zeniheisser requested review from Qubitol and stloufra July 16, 2026 12:39

@stloufra stloufra 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.

Do we care about the formatting CI not passing?

Comment on lines 299 to 308
fi[0] = cxmake( -pvec3 * (fptype)nsf, -pvec3 * (fptype)nsf );
fi[1] = cxzero_sv();
const int nh = nhel * nsf;
const int ip = ( 1 + nh ) / 2;
const int im = ( 1 - nh ) / 2;
const cxtype_sv sqp0p3 = cxmake( fpsqrt( 2. * pvec3 ) * (fptype)nsf, 0. );
fi[2] = fi[1];
if( nh == 1 )
{
fi[3] = fi[1];
fi[4] = sqp0p3;
}
else
{
fi[3] = sqp0p3;
fi[4] = fi[1];
}
fi[3] = ip * fi[1];
fi[4] = im * fi[1];
fi[5] = fi[1];

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.

This does not seem to be right (even though we never exercise this function).

fo[2] = cxzero_sv();
fo[3] = ip * chi1;
fo[4] = im * chi1;
//fo[5] = chi1; // AV: BUG!

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.

Do we need to keep bugs documented in the code?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Agreee, we can remove them.

Comment on lines +329 to +334
const int ip = ( 1 + nh ) / 2;
const int im = ( 1 - nh ) / 2;
const cxtype_sv sqp0p3 = cxmake( fpsqrt( 2. * pvec3 ) * (fptype)nsf, 0. );
fi[2] = fi[1];
if( nh == 1 )
{
fi[3] = fi[1];
fi[4] = sqp0p3;
}
else
{
fi[3] = sqp0p3;
fi[4] = fi[1];
}
fi[3] = ip * fi[1];
fi[4] = im * fi[1];

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.

Same here.

fo[3] = cxmake( ip * nsf * sqm[std::abs( ip )], 0 );
fo[4] = cxmake( im * nsf * sqm[std::abs( im )], 0 );
fo[5] = cxmake( ip * sqm[std::abs( im )], 0 );
const int ipp = -( ( 1 - nh ) / 2 ) * nhel; // NB: Fortran sqm(0:1) also has indexes 0,1 as in C++

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.

Can we reuse ip and im ? :

const int ipp = -im * nhel;

or better yet

const int ipp = ip * nhel;

(not sure if the - adds some clarity from physics point of view)

fi[0] = cxmake( -pvec0 * (fptype)nsf, -pvec3 * (fptype)nsf ); // AV: BUG FIX
fi[1] = cxmake( -pvec1 * (fptype)nsf, -pvec2 * (fptype)nsf ); // AV: BUG FIX
const int nh = nhel * nsf;
const int ip = ( 1 + nh ) / 2;

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.

Not to be pedantic but bit shift would be perfect here instead of /2

@Qubitol Qubitol left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you for modifying this, it looks much more clean.
I fixed few things which also @stloufra pointed out, please check them.
Also, I guess we can remove the stray comments.

fi[3] = sqp0p3;
fi[4] = fi[1];
}
fi[3] = ip * fi[1];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fi[3] = ip * fi[1];
fi[3] = ip * fi[1] + im * sqp0p3;

fi[4] = fi[1];
}
fi[3] = ip * fi[1];
fi[4] = im * fi[1];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fi[4] = im * fi[1];
fi[4] = im * fi[1] + ip * sqp0p3;

fo[2] = cxzero_sv();
fo[3] = ip * chi1;
fo[4] = im * chi1;
//fo[5] = chi1; // AV: BUG!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Agreee, we can remove them.

fi[3] = sqp0p3;
fi[4] = fi[1];
}
fi[3] = ip * fi[1];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fi[3] = ip * fi[1];
fi[3] = ip * fi[1] + im * sqp0p3;

fi[4] = fi[1];
}
fi[3] = ip * fi[1];
fi[4] = im * fi[1];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
fi[4] = im * fi[1];
fi[4] = im * fi[1] + ip * sqp0p3;

@stloufra

Copy link
Copy Markdown
Member

Thanks for the simplification - LGTM

@Qubitol

Qubitol commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Do we care about the formatting CI not passing?

Yes, that needs to be fixed.

Comment on lines +180 to +181
const int ip = ( 1 + nh ) >> 1; // NB: same as in Fortran pp==0, differs from Fortran pp>0, which is (3+nh)/2 because omega(2) has indexes 1,2
const int im = ( 1 - nh ) >> 1; // NB: same as in Fortran pp==0, differs from Fortran pp>0, which is (3-nh)/2 because omega(2) has indexes 1,2

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I reckon bit-shift makes it less readable, is there a real performance gain into using that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Probably none whatsoever, most any compiler will cast integer division by two to a bit shift --- but it does look cooler!

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.

FWIW I would go for more readable rather than cooler ;-)

@zeniheisser

Copy link
Copy Markdown
Contributor Author

@stloufra @Qubitol I've added the bug fixes + another one which didn't appear in the tests due to formatting (cxtype * int implicitly cast to float rather than double) and fixed formatting (also applied to helas_fd.h to make it consistent, although that's not checked by the CI). Also changed integer division to a bit shift --- doesn't matter, but it does look a bit cooler ;-) I'm fine either way, though.

@stloufra , I took your suggestion and recycled the evaluated ip and im for the fermion at rest. I don't know why the plus and minus polarisations are inverted for those, but that's also how the Fortran version are written so I've kept the ipp and imp variables. I presume it's just a way to consistently keep track of rest-state helicity (which isn't well-defined) between initial and final state particles.

@roiser

roiser commented Jul 17, 2026

Copy link
Copy Markdown
Member

Do we care about the formatting CI not passing?

Good point, let's discuss at the next occasion

@zeniheisser

Copy link
Copy Markdown
Contributor Author

For reference, even with the cast to double there is no noticeable runtime difference at O3. Running standalone branchless and original code with everything but IXXXXX and OXXXXXX commented out consecutively for 1024^3 PS points:
(Branch-free) 3a SigmaKin : 1.504317 sec
(Original ver) 3a SigmaKin : 1.526404 sec
(apparently my machine is running a bit hotter today than yesterday hehe)

@zeniheisser
zeniheisser merged commit 578406f into madgraph5:master Jul 17, 2026
205 checks passed
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.

5 participants