Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

[OT] Merry Christmas and gift of love

by marioroy (Prior)
on Dec 25, 2021 at 10:33 UTC ( [id://11139880]=perlmeditation: print w/replies, xml ) Need Help??

Greetings, fellow Monks

This is not Perl related but my friends live here.

I ventured into Python and learned a lot. The theme is parallelization which is my passion. So, what better way to consume CPU cores than to explore the Mandelbrot Set in real time. Included in the GitHub repo are complementary CUDA and OpenCL demonstrations using PyCUDA and PyOpenCL respectively. To make things fast, Numba JITs Python code to C-like performance.

https://github.com/marioroy/mandelbrot-python

The various demonstrations work on FreeBSD, Linux, macOS, and Microsoft Windows. What about threads and GIL? Fortunately, not a problem. Meaning full CPU utilization on Windows. This is possible by specifying nogil=True for Numba and that releases the GIL.

I wanted to finish by Christmas and there it is.

Replies are listed 'Best First'.
Re: [OT] Merry Christmas and gift of love
by kcott (Archbishop) on Dec 25, 2021 at 19:33 UTC

    G'day Mario and Merry Christmas,

    This is great. I've followed all of the links; I'll delve into them in greater detail over the next few days.

    I've been interested in fractals for some decades. Back in the late '90s, I wrote some Perl code to create them: my personal computer didn't have sufficient power to generate these in any useful amount of time; I ran them on a $work machine at ~5pm and got a result the next morning (these were tiny; around 50-100px squares).

    About a decade later, now with a personal machine that could produce these in minutes, rather than hours, I set about exploring the basic Mandelbot algorithm. I was surprised with what I was able to achieve. Take a look at the user image on my "home node". It's an APNG which works in every graphical browser I've tried (including those embedded in small mobile devices). Due to size restictions on this site, I had to greatly reduce the number of transitions; however, you'll still be able to see the morphing of a basic Mandelbrot set into a rather fanciful "K" (my initial letter); a Julia set was applied as a last step purely for beautification purposes. All of the images were created using Tk.

    The original code for this became huge with a massive (although, not unwanted) feature creep: algorithm selections; output choices, and so on. I hadn't used it in a very long time (over ten years) but, after setting up my latest rig, I dug it out and gave it a try. It still worked perfectly (very please about that) and 800px squares completely rendered in a just a few seconds (as you might imagine, even more pleased about that).

    As I'm still on annual leave for the next two weeks, I think I may have a fun project to occupy myself. I'll look into the CUDA demonstrations you indicated, as well as seeing what I can leverage from MCE. A very nice Christmas present — many thanks ++.

    — Ken

      I have a great appreciation for mathematicians. It took me some time to make this. I updated the repo, adding more comments.

      The letter 'k' in your node's image is neat.

      my personal computer didn't have sufficient power to generate these in any useful amount of time

      I know the feeling. I started with the Commodore 64, and doing something like fractals was just painfully slow. Of course, some enterprising people found a way to do multi-processor computing on those: The floppy drive used the same processor as the computer, so if you hooked up multiple of those(*) you could speed up the process quite a lot.

      (*) These were the days of uhm, backing up every game disk you could get your hands on and uh, storing them at all your friends houses for, well, "safekeeping". Having multiple disk drives just sped up the process. Nothing to do at all with software piracy...

      perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
        I started with the Commodore 64, and doing something like fractals was just painfully slow.

        It depended on precisely what you were doing with the fractals. Rescue on Fractalus! was released on the C64 (among many other platforms) and played fairly well AFAIR.


        🦛

Re: [OT] Merry Christmas and gift of love
by etj (Deacon) on Dec 27, 2021 at 07:05 UTC
    Merry Xmas!

    Learning new things is fun. If you'd like to check out PDL's parallelisation (happens automatically now, for suitably-structured ("threadable") problems) and the Mandelbrot set, check out the 2017 "Practical Magick" paper p5-7, including how to visualise it.

      Congratulations on the PDL parallelisation effort.

      Thank you for sharing the article. I'm trying to run the demonstration, beginning on page 6, and encountered a C build failure. See issue on GitHub. Thanks to @mohawk2, this is working.

      Update: Remove the size args to pgswin. Thanks, etj.
      Update: Display the compute time.

      use strict; use warnings; use PDL; use PDL::Graphics::Simple; use Time::HiRes 'time'; no PDL::NiceSlice; # prevents interference use Inline Pdlpp => <<'EOPP'; pp_def('pp_mandel', # Pars (signature) specs threadable arguments. Pars => 'c(n=2); [o]o()', # OtherPars specs scalar arguments. OtherPars => 'int max_it', Code => <<'EOC', // All this code gets wrapped automagically in a thread loop. // It starts a fresh C block, so you can declare stuff up top. // The $GENERIC() macro is the overall expression type. int i; // Iterator $GENERIC() rp0 = $c(n=>0), ip0 = $c(n=>1); // Copy the initial val +ue to rp0/ip0 $GENERIC() rp = rp0, ip = ip0; // Copy again for the i +nitial iteration $GENERIC() rp2 = rp*rp, ip2 = ip*ip; // Find RP^2 and IP^2 f +or magnitude and z^2 // The OtherPars are in the $COMP macro. for(i=$COMP(max_it); rp2+ip2 < 4 && i; i--) { ip *= 2 * rp; rp = rp2 - ip2; // Calculate M_i(z)^2 rp += rp0; ip += ip0; // Add z rp2 = rp*rp; ip2 = ip*ip; // Calculate rp^2 and ip^2 for n +ext time } $o()= i; // Assign the iterator to the output value EOC ); EOPP my $cen = pdl(-0.74897,0.05708); my $coords = $cen + (ndcoords(501,501)/250 - 1) * 0.001; my $w = pgswin(); my $start = time(); $w->image( $coords->using(0,1), $coords->pp_mandel(2500), {title=>"Man +delbrot"} ); print "Compute time: ", time() - $start, $/; print "Press the enter key to exit\n"; <STDIN>;
        Another thing that changed in 2021 (as well as the parallelisation improvements) is that PDL now has native complex numbers, which means the above code could be simplified to using C99 complex numbers rather than manually doing complex-number / magnitude calculations EDIT TO REMOVE size args to pgswin that caused gnuplot to try to make a gigantic window and run out of memory:
        use strict; use warnings; use PDL; use PDL::Graphics::Simple; use Inline Pdlpp => <<'EOPP'; pp_def('pp_mandel', # Pars (signature) specs threadable arguments. Pars => 'coord(n=2); [o]o(); complex [t]c()', # OtherPars specs scalar arguments. OtherPars => 'int max_it', Code => <<'EOC', /* All this code gets wrapped automagically in a thread loop. */ /* The $GENERIC(c) macro is the type of ndarray "c". */ // using the Wikipedia formula: z_{n+1} = {z_n}^2 + c int i; // iterator. $c() = $coord(n=>0) + I*$coord(n=>1); // Copy the initial value $GENERIC(c) z = $c(); // Copy for the initial iteration // the OtherPars are in the $COMP macro. for(i=$COMP(max_it); cabs(z) < 2 && i; i--) z = z*z + $c(); $o()= i; // Assign the iterator to the output value EOC ); EOPP my $cen = pdl(-0.74897,0.05708); my $coords = $cen + (ndcoords(501,501)/250 - 1) * 0.001; my $w = pgswin(); $w->image( $coords->using(0,1), $coords->pp_mandel(2500), {title=>"Mandelbrot"} ); <STDIN>

        EDIT apparently this version takes twice as long to run as the one that doesn't use C99 complex numbers. I assume this is because mine uses cabs, while the other one uses some cleverness to reduce the amount of multiplications etc.

        Thanks for raising the issue, and for fixing it :-D
Re: [OT] Merry Christmas and gift of love
by eyepopslikeamosquito (Archbishop) on Dec 26, 2021 at 04:48 UTC

      That's very neat. It's stunningly beautiful to see the Mandelbrot Set rendered in a terminal. My terminal of 50 rows by 96 columns begged for full screensaver effect.

      #$r=25; $c=80; `resize` =~ /=(\d+).*=(\d+)/s; $c=$1,$r=$2;
Re: [OT] Merry Christmas and gift of love
by bliako (Monsignor) on Dec 27, 2021 at 17:02 UTC

    Thanks marioroy++ for this present. And happy festivus to all from me as well.

    A slight complication: in my linux box the cuda compiler (nvcc) needs some specific gcc versions (for nvcc v 10.1, 10.2, gcc version must be 8). If there are multiple compilers, nvcc must be told where the compiler to use, resides via e.g. --compiler-bindir=/usr/local/gcc84/bin (and make sure that in that dir there are executables or links named gcc,c++,cpp). I found that placing a line (my first and only, I hope, interaction with the Serpent for this year!) '--compiler-bindir=/usr/local/gcc84/bin', in mandel_cuda.py, line 57 (e.g. where the options array is set), compiles your program and yep! it shows spectacularly my holy-grail since the years I was still sucking on my Alma Mater's mamma (at the guts, in the Sun-Sparkstations dungeon).

    I have also encountered the problem that pycuda would not install (via pip3 as per your instructions) because it did not know where my cuda-sdk installation was. I solved that with export CPATH=$CPATH:/usr/local/cuda/include; export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/cuda/lib64

    bw, bliako

      Thank you for the report, bliako.

      One may specify the compiler-bindir option. CPATH and LIBRARY_PATH environment variables are appended in mandel_cuda.py, before importing the Python CUDA module. See update.

Re: [OT] Merry Christmas and gift of love
by marioroy (Prior) on Jan 13, 2022 at 17:57 UTC

    Hello friends of the monastery,

    The project includes a demo folder, non-parallel demonstrations for computing the Mandelbrot Set, apply Anti-Aliasing, Gaussian Blur, and Unsharp Mask via a step-by-step approach. Since the initial announcement, I also added pure-Python code for running on the GPU via @cuda.jit.

Re: [OT] Merry Christmas and gift of love
by Discipulus (Canon) on Dec 26, 2021 at 17:15 UTC
    > but my friends live here

    thanks! and merry Christmas to you too!

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
    !
Re: [OT] Merry Christmas and gift of love
by LanX (Saint) on Dec 25, 2021 at 19:27 UTC

      No conclusion. I wanted to learn Python by making something with it. The journey spanned about half a year on and off.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://11139880]
Approved by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (6)
As of 2024-04-16 07:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found