Tuesday, December 6, 2011

Threading in plugin code

I'm trying to write a plugin that does some very time-consuming image processing, and I'm trying to use multiple threads to improve performance. I first tried using OpenMP, which worked fine, except that if we executed any OpenMP pragma (even a critical or atomic), Photoshop would crash later (after the plugin is closed).

So, I concluded that Photoshop and OpenMP don't get along, and I switched to using Intel's Threading Building Blocks library. With that, I get similar behavior - executing any parallel algorithm, even if I've only got one thread, and even if I don't *do* anything inside the parallel block, causes Photoshop to crash on exit.

Has anybody done something like this successfully? Was there a trick to it? I could write threads by hand, but I don't have any reason to believe that it's going to work any better.

For what it's worth, all of this threading is happening inside a static library built using the Intel C++ compiler v10.1, linked into a plugin built using GCC 4.0. Needless to say, all of this code works perfectly in my test applications.

Thanks,
AaronThreading in plugin code
And why you are not using destination OS threading functions? E.g. pthread for mac and Winbase.h in Win.

Do you join threads before you quit plugin?

I noticed also mystical crashes of Photoshop (not related to threading) but when used particular Carbon string functions on Mac. This is fracking magic and you have to play with it.

PS:
It has to work but you can not spawn threads and then return main thread from plugin to Photoshop I think if you do so.

And I would consider all suites calls as critical sections, avoiding using suites from multiple threads simultaneously.

PS2:
And I would debug Photoshop, I had to do this several times. Just run it attach debugger if it crashes you will probably see where the problem is, maybe it's in threading library somewhere.Threading in plugin code
Don't call Photoshop functions via FilterRecord from other threads!
Photoshop API isn't thread-safe.
First, I'm using OpenMP and/or TBB because it's a hell of a lot easier, more efficient, and more cross-platform than using native threads. I could do it with native threads, and it's possible that it would work, but I'm saving that for a last resort.

Second, I'm not doing anything at all in my threads at the moment - in the case of OpenMP, if the code encounters *any* OpenMP pragmas at all, even just a critical or atomic, Photoshop will crash later. If there are no pragmas, there's no crash. I don't have to even create threads for this to happen.

I can attach a debugger to Photoshop, but when it crashes it's nowhere near my code. The actual crash (in the OpenMP case) occurs in Photoshop's Open dialog, and only when it's in thumbnail view. No idea why.

I have to partially retract my statement about TBB. The crash that I'm seeing seems not to be directly related to TBB calls, but I haven't yet figured out what it is. It's possible that in the course of switching over to TBB I managed to break something else - I'm investigating this now. This may yet be a workable solution.

Thanks,
Aaron
No, I was right the first time. Making a single call to tbb::parallel_for will cause Photoshop to crash on exit. This happens even if I've initialized TBB with a single thread (so there's no actual parallelism going on), and even if the body of my algorithm doesn't do anything.

Aaron
This is known as ''a world of hurt''... just based on your description (I've never tried it, but would expect pretty much the amount of pain you found).

Adobe really needs to document this stuff better.
I quickly took a look at intel web site and there is sentence
(http://softwarecommunity.intel.com/articles/eng/1197.htm)

''At the end of the parallel region, threads are suspended''

Therefore I asked question if you join threads if you leave plugin.

You have to ensure that you quit all threads when leaving plugin, but it's quesiton how to achieve this with OpenMP.

So start plugin in debugger and watch threads, if the threads remain after processing quit from plugin then this is problem.
I got it working using Threading Building Blocks. My original problem with TBB seems to have been resolved by explicitly releasing all PS suites when the plugin closes (including those acquired by PS code). I did this by making a wrapper around the basic suite that tracks suite acquisitions, and then releasing them all by hand when my filter closes.

Never got OpenMP to work. There wasn't an issue with joining threads, because I'm threading only a small part of my process - by the time I close the filter, it's long since over.

Thanks,
Aaron
  • parameter
  • No comments:

    Post a Comment