Page 1 of 2

Loading JPEG images in parallel

Posted: 2014-04-28T11:53:25-07:00
by porridge
Hello,

Since I think this is more about internals than usage, I decided to post in this forum, hope it's OK.

I'm using the gographics/imagick Go language binding for imagemagick in my program, whose main function is to load, resize and save a lot of JPEG files as fast as possible (in parallel). After doing some experiments I came to the conclusion that the bottleneck is loading pictures, and what is more, it seems it is performed serially.

After taking a dive into imagemagick sources (version 6.6.9.7 as this is what Ubuntu 12.04 precise has) I've discovered that magick/constitute.c:ReadImage seems to be acquiring a mutex if the codec does not support threading:

Code: Select all

if (GetDelegateThreadSupport(delegate_info) == MagickFalse)
  LockSemaphoreInfo(constitute_semaphore);                 
A quick grep for NoThreadSupport seems to indicate that one of the few codecs which does not support threading is coders/jpeg.c, which is the one I care about most :-(

Some questions:
- is the above assessment correct, or did I get something wrong?
- why is there no thread support for JPEG codec?
- are there plans to change this?
- do I have any other options?

regards,

Marcin

Re: Loading JPEG images in parallel

Posted: 2014-04-28T12:51:03-07:00
by magick
The JPEG delegate library is not thread safe so ImageMagick must single thread the JPEG library.

Re: Loading JPEG images in parallel

Posted: 2014-04-29T11:32:02-07:00
by porridge
Thanks, this answers the first two questions. Should I understand that there are no plans to change this, nor there are any ways around it?

Re: Loading JPEG images in parallel

Posted: 2014-04-29T11:42:30-07:00
by magick
The only way to change it is to make the JPEG library thread safe. We didn't write the JPEG library. If you want it thread safe, send a note to the JPEG developers. Once its thread-safe, we can remove the mutex from ImageMagick.

Re: Loading JPEG images in parallel

Posted: 2014-05-04T12:06:52-07:00
by porridge
Could you please expand a bit on what makes the jpeg library thread-unsafe? I've found two threads about thread-safety of libjpeg-turbo (which seems to be what imagemagick is linked against at least on Ubuntu). The first[1] mentions usage of setjmp/longjmp and the other[2] the fact that tjGetErrorStr() does not take a tjhandle argument.

Is one of them the issue you have in mind? Or are they perhaps one and the same thing (I haven't looked at the code).

1. http://sourceforge.net/p/libjpeg-turbo/ ... /28603968/
2. http://sourceforge.net/p/libjpeg-turbo/ ... /30335490/

Re: Loading JPEG images in parallel

Posted: 2014-05-04T14:52:54-07:00
by magick
That is a question for the JPEG developers. The JPEG delegate library includes the file libjpeg.txt that says: "Note: the JPEG library currently is not thread-safe."

Re: Loading JPEG images in parallel

Posted: 2014-05-06T11:37:50-07:00
by porridge
Hm, I had a look at that file in version 8d, and it says:
[...]
This is discussed further under "I/O suspension", above. (Note: the JPEG
library currently is not thread-safe. You must not call jpeg_consume_input()
from one thread of control if a different library routine is working on the
same JPEG object in another thread.)
[...]
The parentheses suggest that lack of thread safety only applies to multiple threads working on the same JPEG object. If my interpretation is correct, then I think it would make sense to have a mutex per image handle, rather than a global one (which is currently the case, right)?

Re: Loading JPEG images in parallel

Posted: 2014-05-06T12:25:52-07:00
by magick
If you can confirm with the JPEG developers that JPEG is thread safe as you suggest-- we will enable multiple threads for the JPEG coder in the next release of ImageMagick. We do have the setjmp() issue but we may be able to work around that.

Re: Loading JPEG images in parallel

Posted: 2014-05-10T13:00:30-07:00
by porridge
Here's what I got from one of the libjpeg developers:
Guido Vollbeding <guido@jpegclub.org>
The parentheses suggest that lack of thread safety only applies to multiple threads working on the same JPEG object. I'd like to clarify if it is fine to have multiple concurrent threads using libjpeg8 if they work on separate jpeg objects.
Yes, you are totally right here, I have nothing to add.

Re: Loading JPEG images in parallel

Posted: 2014-09-17T03:37:21-07:00
by englishl1989
Can you confirm if and/or what version of ImageMagick this has been added to?

Re: Loading JPEG images in parallel

Posted: 2014-09-17T04:23:28-07:00
by magick
ImageMagick 6.8.9-8, available in a few weeks.

Re: Loading JPEG images in parallel

Posted: 2014-09-17T04:28:55-07:00
by englishl1989
Brilliant, thank you.

Re: Loading JPEG images in parallel

Posted: 2014-12-13T14:49:03-07:00
by porridge
Hello again,
I tried running my program against imagemagick library version 6.8.9.9-3 as distributed by Debian and unfortunately still at most one image decoding thead seems to be running at a time. I had a look at the source and I can see the ifdefs such as:

#if JPEG_LIB_VERSION < 80
entry->thread_support=NoThreadSupport;
#endif

which at first sight looked promising. However given that that value is simply zero:

./magick/magick.h: NoThreadSupport = 0x0000,

it seems to me that not setting thread_support to any value is equivalent to setting it to NoThreadSupport.

Could you let me know if what I write make sense or is just a red herring?

Re: Loading JPEG images in parallel

Posted: 2014-12-13T15:36:01-07:00
by magick
Notice the call to SetMagickInfo(). It initializes the thread support, by default, to DecoderThreadSupport | EncoderThreadSupport).

Re: Loading JPEG images in parallel

Posted: 2014-12-14T00:40:48-07:00
by porridge
Thank you for the fast response, I'll keep digging.