It revealed a quirk to Inline::Pdlpp, which makes/loads the XS code, but drops the Perl code, so PMCode gets ignored. I've added that to the doc which will be in next release.--- collatz.orig 2024-07-27 23:53:49.665967800 +0100 +++ collatz 2024-07-28 03:21:55.085180253 +0100 @@ -119,11 +119,19 @@ return ( $number, $highest ); } +use Inline Pdlpp => 'DATA', clean_after_build => 0; +sub PDL::collatz_pdl { + PDL::_collatz_pdl_int(@_, my $n = PDL->null, my $h = PDL->null); + # Perl scalars because is across forked processes in MCE + map $_->sclr, $n, $h; +} + no warnings 'once'; #*collatz = \&collatz_longest; # choose collatz here #*collatz = \&collatz_longest_c1; # using T(x) notation - *collatz = \&collatz_longest_c2; # using compiler intrinsics +#*collatz = \&collatz_longest_c2; # using compiler intrinsics + *collatz = \&PDL::collatz_pdl; # using PDL my $m = shift || '1e7'; my ( @sizes, $chunk_size ); @@ -151,3 +159,27 @@ say "@$_" for ( sort { $a->[0] <=> $b->[0] } grep { $_->[1] == $highest } @sizes )[ 0..0 ]; + +__DATA__ +__Pdlpp__ +pp_def('collatz_pdl', + Pars => 'beg(); end(); [o]number(); [o]highest()', + GenericTypes => ['Q'], + PMCode => '', # trigger the _int but keep the Perl code in main bod +y + Code => ' + PDL_Indx i, number = 0, highest = 0; + for ( i = $end(); i >= $beg(); i-- ) { + PDL_Indx n = i, steps = 0; + /* count using the T(x) notation */ + do { + n % 2 ? ( steps += 2, n = (3 * n + 1) >> 1 ) + : ( steps += 1, n = n >> 1 ); + } while ( n != 1 ); + if ( steps >= highest ) { + number = i, highest = steps; + } + } + $number() = number; + $highest() = highest; + ', +);
The most idiomatic way to get PDL to do this would be to broadcast the above operation over a higher dim that has as many things in its as cores you have, and let the PDL pthreads do their thing instead of MCE. That would have the challenge that the Collatz stuff is quite non-deterministic in processing need, which reminds me that I've meant for a while to break PDL pthreading into smaller chunks and distribute across a thread pool which would mitigate this. PRs to beat me to it very welcome!
A PDL solution doesn't work great in MCE because the outputs needed to be converted to Perl scalars to be successfully passed across forked processes.
In reply to Re: Longest Collatz using MCE::Flow, Inline::C, and GCC compiler intrinsics
by etj
in thread Longest Collatz using MCE::Flow, Inline::C, and GCC compiler intrinsics
by marioroy
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |