Skip to content

Instantly share code, notes, and snippets.

@krakjoe
Last active October 8, 2015 08:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save krakjoe/9274747 to your computer and use it in GitHub Desktop.
Save krakjoe/9274747 to your computer and use it in GitHub Desktop.
mandel pthreads

This is a rather extreme test ... still, was fun ...

[joe@fiji pthreads]$ time php-zts ../php-src/mandrel.php 0 128

real	0m11.441s
user	0m11.386s
sys	0m0.043s
[joe@fiji pthreads]$ time php-zts ../php-src/mandrel.php 1 128

real	0m2.951s
user	0m21.308s
sys	0m0.243s
[joe@fiji pthreads]$ time php-zts ../php-src/mandrel.php 0 256

real	0m19.072s
user	0m19.010s
sys	0m0.044s
[joe@fiji pthreads]$ time php-zts ../php-src/mandrel.php 1 256

real	0m4.786s
user	0m36.023s
sys	0m0.247s

I used as many threads as I have cores, the only sensible number to use ;)

mandel

<?php
/*
* requires pthreads, obviously !!
* usage:
* php mandel.php 1 128 - run with threads, 128 iterations
* php mandel.php 0 128 - run without threads, 128 iterations
* Disclaimer: I know nothing about images, code from:
* http://code.activestate.com/recipes/577680-multi-threaded-mandelbrot-fractal/
*/
class Render extends Thread {
public function __construct(Mandel $mandel, $id, $max, $img) {
$this->mandel = $mandel;
$this->id = $id;
$this->max = $max;
$this->img = $img;
}
public function run() {
$mandel = $this->mandel;
$iterations = $mandel->getIterations();
$range = range(
$this->id,
$mandel->getSum(),
$this->max);
$width = $mandel->getWidth();
$height = $mandel->getHeight();
$draw = $mandel->getDraw();
$image = $this->img;
foreach ($range as $pixel) {
$kx = $pixel % $width;
$ky = (int) $pixel / $width;
$a = $draw["xa"] +
$draw["xd"] * $kx / ($width - 1.0);
$b = $b = $draw["ya"] +
$draw["yd"] * $ky / ($height - 1.0);
$x = $a;
$y = $b;
for ($it = 0; $it < $iterations; $it++) {
$x0 = $x * $x - $y * $y + $a;
$y = 2.0 * $x * $y + $b;
$x = $x0;
if ($x * $x + $y * $y > 4) {
$c = imagecolorallocate(
$image,
($it % 8) * 32,
(16 - $it % 16) * 16,
($it % 16) * 16);
imagesetpixel(
$image, $kx, $ky, $c);
break;
}
}
}
}
protected $mandel;
protected $id;
protected $max;
protected $img;
}
class Mandel extends Stackable {
public function __construct($width, $height, $iterations) {
$this->width = $width;
$this->height = $height;
$this->sum = $this->width *
$this->height;
$this->iterations = $iterations;
$this->draw = [
"xa" => -2,
"xb" => 1.0,
"ya" => -1.5,
"yb" => 1.5,
"xd" => 1.0 - (-2),
"yd" => 1.5 - (-1.5)
];
}
public function getIterations() { return $this->iterations; }
public function getDraw() { return $this->draw; }
public function getSum() { return $this->sum; }
public function getWidth() { return $this->width; }
public function getHeight() { return $this->height; }
public function createImage() {
return imagecreatetruecolor(
$this->width, $this->height);
}
public function run(){}
protected $width;
protected $height;
protected $sum;
protected $iterations;
protected $draw;
}
$threaded = isset($argv[1]) ? intval($argv[1]) : 1;
$iterations = isset($argv[2]) ? intval($argv[2]) : 64;
$mandel = new Mandel(1920, 1280, $iterations);
$image = $mandel->createImage();
$threads = []; # array of threads
$thread = 0; # current thread identifier
$max = 8; # maximum number of threads
while ($thread<$max) { # create all threads, or not
$threads[$thread] = new Render(
$mandel, $thread, $max, $image);
if (!$threaded) {
$threads[$thread]->run();
} else $threads[$thread]->start();
$thread++;
}
if ($threaded) {
foreach ($threads as $thread)
$thread->join();
}
imagepng($image, "mandel.png"); # dump image
?>
@DeeFuse
Copy link

DeeFuse commented Jun 15, 2015

If you want to render Larger images, you may get into memory allocation trouble because of the huge amount of items in $range.
Also the statement $image = $this->img; will use a lot of memory.

I would suggest removing L24-L27 and L31
Replacing L33 with:

        for($pixel=$this->id;$pixel<=$mandel->getSum();$pixel+=$this->max) {

And $imagein L49 and L55 with $this->img

With this changes I've made a 15306x10240px @ 8 Threads with 256 Iterations without problems.

@Jan-E
Copy link

Jan-E commented Oct 8, 2015

https://gist.github.com/krakjoe/9274747#file-mandel-php-L68 should be

class Mandel extends Threaded {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment