Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^2: Imager: Gateway Timeout (OMP)

by vr (Curate)
on Dec 25, 2019 at 01:26 UTC ( [id://11110605]=note: print w/replies, xml ) Need Help??


in reply to Re: Imager: Gateway Timeout
in thread Imager: Gateway Timeout

I thought using "degrees" with Imager::rotate was demonstrated to be too slow. I should have said, perhaps, that timings for my previous answer were taken at very old machine, but principle remains the same. Addressing (partially) some of your remarks, (1) I suspect prejudice against GD w.r.t. colour is because "$truecolor" boolean argument was not supplied to its newFromXXX methods; (2) it requires either special test images (example), or, with usual day-to-day photos, quite some training to see re-sampling artefacts, but, for the love of god, please don't use nearest-neighbour interpolation for anything but thumbnail size previews; (3) GD is listed as available for ActiveState PPM and is pre-installed with Strawberry Perl; (4) source image must be physically rotated before being sent to printer? is that so?

It's good you're moving forward with solving the problem, and you can skip what follows -- sorry to hijack this thread for a little demo, moreover not sure if it's exactly 100% Perl. Assuming the task "open jpg/scale1/scale2/rotate original file/save all" exists, downsampling with reasonable quality appears to be quite fast, and slowest part is rotation. I looked here and there, and it seems, for rotation, GD is faster than Imager, and PDL::IO::Image is faster yet. I'd say the latter is wrapper for (some of) FreeImage functions, with abilities to export image data to piddles, and "PDL" in its name doesn't mean that anything PDL-related is required to be used at all.

Looking into FreeImage, it reminded me of lossless JPG transformations, right-angle rotation among them, which is (a) good because it preserves quality, (b) fast because it doesn't require total (de/en)coding. Not implemented in PDL::IO::Image, can't find anything similar on CPAN. Closest would be shelling out and using CL tools.

However, I felt it's good opportunity to also test/demo a kind of parallelization not very frequent with Perl, i.e. OMP. Test subject is 4009*3521 image, let's pretend 8 such files are to be rotated, using reasonably recent i5 with 4 cores, hence "4" threads below. Changing it to "1" results in ~3.5 seconds for FreeImage, still quite faster than GD because of (b). I copied filenames in Perl array to C array so that no Perl functions/macros are used in fragment to be run in parallel, because they are not re-entrant(?). I used pre-compiled FreeImage dll with Strawberry Perl, should be possible to install OS package under Linux.

use strict; use warnings; use Time::HiRes 'time'; use GD; use File::Copy 'copy'; use constant ORIG => 'potw1949a'; my @list; # list of filenames w/o extension for ( 1 .. 8 ) { # 8 copies my $s = ORIG . $_; push @list, $s; copy ORIG . '.jpg', "$s.jpg" or die; } ############### GD my $t = time; for ( @list ) { GD::Image-> newFromJpeg( "$_.jpg", 1 ) -> copyRotateInterpolated( 90, 0 ) -> _file( "$_+.jpg" ); } printf "GD, sequential, %.2f s\n", time - $t; ############### FreeImage $t = time; parallel( \@list ); printf "FreeImage, parallel, %.2f s\n", time - $t; unlink glob ORIG . '?.jpg'; unlink glob ORIG . '?+.jpg'; use Inline C => config => ccflagsex => '-fopenmp', LIBS => '-lgomp -lFreeImage'; use Inline C => <<'END_OF_C'; #include <FreeImage.h> #include <omp.h> void parallel(SV *array) { int i, nfiles, len; char *fname, *tmp; char **fnames; nfiles = av_len((AV *)SvRV(array)); fnames = malloc((nfiles + 1) * sizeof(char*)); for (i = 0; i <= nfiles; i++) { tmp = SvPV(*av_fetch((AV *)SvRV(array), i, 0), len); fname = malloc(len + 1); memcpy(fname, tmp, len + 1); fnames[i] = fname; } #pragma omp parallel num_threads (4) { #pragma omp for for (i = 0; i <= nfiles; i++) { char *src, *dst; asprintf(&src, "%s%s", fnames[i], ".jpg" ); asprintf(&dst, "%s%s", fnames[i], "+.jpg" ); FreeImage_JPEGTransform(src, dst, FIJPEG_OP_ROTATE_90, 0); } } for (i = 0; i <= nfiles; i++) free(fnames[i]); free(fnames); } END_OF_C __END__ GD, sequential, 7.00 s FreeImage, parallel, 1.14 s

Edit: Fixed off-by-one error with array length in C code, + couple most obvious "bugs" with my English. Ubuntu (Debian) FreeImage package has "FreeImage_JPEGTransform" family of functions disabled, had to compile from source. Interesting, under Linux GD performs twice as fast and so is slightly ahead of single-threaded FreeImage.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (5)
As of 2024-04-19 03:22 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found