#1 2011-08-03 12:04:43

Yann
Member
Registered: 2011-08-03
Posts: 2

Rendre jpegdec compatible multithread

Hi Arnaud, I'm testing your jpegdec unit, it's a very good work but it isn't compatible with multithreading...is there a way to adapt it ? I've also tried GDI+ to read my jpg, but its slower than your unit and GDI+ raise some "GDI+ Out Of Memory" errors randomly...I would be verry happy with a multithreaded version of your unit which I use with Graphics32, here is a ToBitmap32 function that you may add to your unit :

function TJpegDecode.ToBitmap32: TBitmap32;
var
  BMI: TBitmapInfo;
begin
  result := TBitmap32.Create;
  ToBMI(BMI);
  result.SetSize( abs( BMI.bmiHeader.biWidth ), abs( BMI.bmiHeader.biHeight ) );
  CopyMemory( @Result.Bits[0], pRGB, result.width*result.height*(bitsPixel div 8));
end;

Thanks for your great work,

Regards,

Yann

Offline

#2 2011-08-03 12:33:03

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,368
Website

Re: Rendre jpegdec compatible multithread

I don't know why jpegdec is not compatible with multithreads...

In the code, there is no global variables, only memory allocated via VirtualAlloc, which is thread-safe AFAIK...

I confess I've no idea why it's not thread-safe...

What is your exact issue? Are you sure the error is inside jpegdec?

Offline

#3 2011-08-03 23:45:04

Yann
Member
Registered: 2011-08-03
Posts: 2

Re: Rendre jpegdec compatible multithread

Yes Arnaud I'm sure...I use your unit to make thumbnails (in a background thread) and display them (in the main app thread). If I use your unit in the 2 threads it raises an access violation. If I use it only in one thread (to make thumbs OR to display them) it works flawlessly. Or if I call you unit from the background thread through Synchronize (which calls it from the main thread) it works again...but has obviously no interest.

The EAccessViolation message is "Access violation at address xxxxxxxxxx. Write of adress 00000001."

I think that your unit allocate memory from one thread which is not accessible from the other one...

Thanks again.

PS : your email address abouchez-AT-magic.fr shared on your website http://bouchez.info/ is no more available (error 550 from the smtp server). Not found another way to contact you (I'm french also !)

Offline

#4 2017-01-14 15:04:24

MarkTG
Member
Registered: 2017-01-14
Posts: 5

Re: Rendre jpegdec compatible multithread

For the benefit of anyone wanting a thread safe version of JpegDec, I've made an updated version of the library available here:

http://www.marktg.com/jpegdec

The original code wasn't thread safe because it used a global variable to store a value - trying to use the code from multiple threads caused an exception. I've modified the assembler code to instead store the value on the stack.

Some performance statistics:

CPU: Intel(R) Core(TM) i7-4810MQ CPU @ 2.80GHz
Core Count: 4
Thread Count: 8
Iterations: 1000
Thread Count: 8

JpegDec:
Single Threaded Performance: 138 images per second
Multithreaded Performance:   439 images per second
Relative Performance: 318%

SynGdiPlus:
Single Threaded Performance: 117 images per second
Multithreaded Performance:   131 images per second
Relative Performance: 112%

Standard Delphi:
Single Threaded Performance: 26 images per second
Multithreaded Performance:   151 images per second
Relative Performance: 581%

Offline

#5 2017-01-14 17:12:55

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,368
Website

Re: Rendre jpegdec compatible multithread

Great!

I've updated the https://synopse.info/files/jpegdec.zip file.

Thanks a lot for sharing!

Offline

#6 2017-01-15 00:53:35

MarkTG
Member
Registered: 2017-01-14
Posts: 5

Re: Rendre jpegdec compatible multithread

No problem - sharing is all in the spirit of open source!

I've copied your zip file over to my web site as a backup and added a link back to your server in case there are any future updates.

Thanks for all your work in adapting this library for Delphi in the first place!

Offline

#7 2017-01-15 06:29:21

zed
Member
From: Belarus
Registered: 2015-02-26
Posts: 102

Re: Rendre jpegdec compatible multithread

@MarkTG
Did you know about libjpeg-turbo? I think, that this is the fastest library to work with jpeg.

You can find Delphi wrapper and helper classes (feel free to optimize it!) here: https://bitbucket.org/sas_team/sas.plan … s/LibJpeg/

It would be great to see performance statistics for it wink

Last edited by zed (2017-01-15 06:36:54)

Offline

#8 2017-01-15 07:39:11

MarkTG
Member
Registered: 2017-01-14
Posts: 5

Re: Rendre jpegdec compatible multithread

@zed

Thanks for the suggestion.

I haven't fully tested it yet, but in my initial testing, single threaded performance with LibJpeg is only a bit over half that of JpegDec - and that's without converting the end result to a TBitmap which would slow it down even further (There doesn't appear to be any included code to convert to TBitmap so I'll need to add some code to convert from Scanlines)

Even when multithreaded, JpegDec is still about 50% faster, and again, the difference will only get bigger once I add code to convert to a TBitmap!

Of course, YMMV on different hardware...

Offline

#9 2017-01-17 14:39:04

MarkTG
Member
Registered: 2017-01-14
Posts: 5

Re: Rendre jpegdec compatible multithread

OK, it turns out that in my previous testing, I was only using the standard LibJpeg and not LibJpeg-Turbo.

With some optimizations of my own code, I've now got the following results:

Iterations: 1000
Thread Count: 8

CPU: Intel(R) Core(TM) i7-4810MQ CPU @ 2.80GHz
Core Count: 4
Thread Count: 8

LibJpeg-Turbo:
Single Threaded Performance: 205 images per second
Multithreaded Performance:   801 images per second
Relative Performance: 391%

JpegDec:
Single Threaded Performance: 166 images per second
Multithreaded Performance:   593 images per second
Relative Performance: 357%

SynGdiPlus:
Single Threaded Performance: 149 images per second
Multithreaded Performance:   147 images per second
Relative Performance: 99%

NativeJPG:
Single Threaded Performance: 22 images per second
Multithreaded Performance:   91 images per second
Relative Performance: 414%

Standard Delphi:
Single Threaded Performance: 26 images per second
Multithreaded Performance:   165 images per second
Relative Performance: 635%


If I disable the conversion to TBitmap, I get the following results:

Iterations: 4000
Thread Count: 8

CPU: Intel(R) Core(TM) i7-4810MQ CPU @ 2.80GHz
Core Count: 4
Thread Count: 8

LibJpeg:
Single Threaded Performance: 232 images per second
Multithreaded Performance:   1082 images per second
Relative Performance: 466%

JpegDec:
Single Threaded Performance: 179 images per second
Multithreaded Performance:   728 images per second
Relative Performance: 407%


I'm planning to update the files on my web site some time tomorrow.

Offline

#10 2017-01-18 12:22:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,368
Website

Re: Rendre jpegdec compatible multithread

Nice numbers!

1. What about Jpeg compression?

2. What about using the TurboJPEG C API?
This API sounds easier to work with in practice.
Is there any Delphi conversion of the headers?

Offline

#11 2017-01-18 12:39:48

MarkTG
Member
Registered: 2017-01-14
Posts: 5

Re: Rendre jpegdec compatible multithread

I haven't done any recent testing on Jpeg Compression.  I don't have a huge requirement for fast compression, so I wasn't thinking about doing testing for that, but it might make sense to do that as well.

At the moment, I don't see much point in using the TurboJPEG C API - as far as I can tell, the TurboJPEG C API for LibJpeg-Turbo is just a wrapper around the standard LibJpeg API, so it's unlikely to give any performance benefits - I expect that it's more likely to hinder performance slightly. 

I haven't found a Delphi conversion for the TurboJPEG API and since I don't expect there to be any benefit from using it, I don't think it's worth the effort to do the conversion as the existing LibJpeg Pascal interface code that Zed linked to seems to work.  Converting to TBitmap wasn't straight forward though with that API which is probably why I hadn't tried it previously - I'm thinking about modifying the existing library code to make it easy to convert to TBitmap since I've already done most of the work...

Offline

Board footer

Powered by FluxBB