Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Eugenio · Jul 04, 2013 at 01:06 PM · threadingforparallel

How to create a parallel for in Unity

Hello everyone. I know that mono doesn't support the System.Threading package but I would like to try to accellerate a texture creation by using something like:

 Color[] dest, source;

 // a lot of stuff...

 void Update (){

    // some other stuff...
    
    Parallel.For (0, texture.height, y => {
       for (int x = 0; x < texture.width; x++) {
          int sourceIndex = (y * texture.width) + x;
          dest[sourceIndex].r = source[sourceIndex].r;
          dest[sourceIndex].g = source[sourceIndex].g;
          dest[sourceIndex].b = source[sourceIndex].b;
       }
    });

    // some other stuff...
 }

Do you think is it possible to do this parallel execution in Unity?

Thanks :)

Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benproductions1 · Jul 05, 2013 at 08:18 AM 0
Share

The Unity API is not thread safe. You will need to either use a different API or create your own to be able to do that

avatar image Eugenio · Jul 05, 2013 at 11:08 AM 0
Share

yes... I know. I was looking for some advice about how to do it using the C# threads or if maybe exists some kind of DLL to use to make a parallel calculation. I was thinking of writing my own C++ library to use the C++ parallel_for... but I don't know if this could be the best and fast solution.

avatar image SinisterRainbow · Jul 05, 2013 at 01:09 PM 0
Share

Isn't there a way to write C/C++ in unity? It would certainly add some speed up..

avatar image Eugenio · Jul 05, 2013 at 04:10 PM 0
Share

Well... if you want to add some C/C++ code to Unity you must have Unity Pro and compile a DLL. Then you can use it by placing your compiled library in the Plugin folder of your Unity project. After that you have to write a C# wrapper that declare the exported symbols of your DLL so you can use in the others C# scripts.

avatar image SinisterRainbow · Jul 05, 2013 at 04:19 PM 0
Share

not fun, but if critical what else can you do.. maybe you can get away with processing it on the graphics card, but i'm not very familiar with GL.

Show more comments

4 Replies

· Add your reply
  • Sort: 
avatar image
9
Best Answer

Answer by CHPedersen · Jul 08, 2013 at 10:56 AM

Actually, though the general rule is that the Unity API is off-limits in separate threads, there are notable exceptions... And the Color class is one of them. It's also perfectly legal to access the static methods in Mathf, or writing into the console using Debug.Log, even though those are actually members of the UnityEngine namespace.

Study, for example, this wiki post by Eric5h5 which uses the Color class in separate threads while scaling a texture. You can do that just fine because it operates on "off-line" objects, so to speak. The offending part about separate threads and Unity only pertains to things that directly affect the real-time renderstate. That is, instantiating GameObjects, changing the transform of something, replacing a material, etc.

In your case, it looks to me like you're trying to parallelize the deep-copying of one texture's colors into another array, right? You can do that concurrently pretty easily by just instantiating a thread per row in the original texture. You already have the algorithm for accessing rows when flattened to a 1D array, and you don't even need to synchronize the threads' access to the array, because they won't be writing to the same area of the array as they handle one row each.

Make a method that takes object as parameter and start threads using ParameterizedThreadStart, passing the y variable as the parameter. In the method, cast the object back to an int, then use that to calculate the row of indices which are the write targets for that particular thread. Then, in the mainthread, loop over the height (the y's) and start a thread for each. It will look something pretty close to this:

 Color[] dest, source;

 Texture2D texture;


 private void StartThreads()
 {
     for (int i = 0; i < texture.height; i++)
     {
         System.Threading.ParameterizedThreadStart pts = new System.Threading.ParameterizedThreadStart(ThreadedColorCopy);
         System.Threading.Thread workerForOneRow = new System.Threading.Thread(pts);
         workerForOneRow.Start(i);
     }
 }

 private void ThreadedColorCopy(object yVariable)
 {
     int y = (int)yVariable;

     for (int x = 0; x < texture.width; x++)
     {
         int sourceIndex = (y * texture.width) + x;
         dest[sourceIndex].r = source[sourceIndex].r;
         dest[sourceIndex].g = source[sourceIndex].g;
         dest[sourceIndex].b = source[sourceIndex].b;
     }
 }

(The above is untested but might work out of the box)

Caveat: It strikes me that one thread per row might be a little too aggressively multithreaded, as it would create 512 separate threads for a 512x512 texture. Instead, it might be an idea to give each thread a region of multiple rows, i.e. one thread handles rows 0-19, thread two handles rows 20-39, etc. You get the idea. It will make the code slightly more complicated, but probably more robust.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Benproductions1 · Jul 08, 2013 at 11:01 AM 0
Share

Thumbs up for good answer

avatar image Eugenio · Jul 08, 2013 at 01:26 PM 0
Share

Believe it or not, this is exactly what I'm currently writing. as soon as I will finish and test the code I'll post my solution. Thank you very much man !!!!

avatar image martijn-vegas · Jul 07, 2015 at 08:38 AM 0
Share

Currently busy with the same problem. I did an performance test.

 for (int j =  texture.width - 1; j >= 0; j--) 

Is allot faster

avatar image Sisso · Jul 07, 2015 at 12:43 PM 0
Share

Talking about optimizations. You should always try to use a thread pool.

Thread are expensive resources (not so hard but are). If you have more threads than CPU cores, for a pure processing (no waiting threads) you will losing a lot of time with thread switching overhead.

avatar image
1

Answer by Eugenio · Jul 08, 2013 at 03:32 PM

Ok guys this is my solution. You can also set how many threads you want to use. For me works like a charm !!! ;) Hope it can be good for anyone else:

 public int threadsToUse = 5;
   
 Color[] dest, source;
 Texture2D texture;

 int threadsStarted, threadsCompleted;
 int pixelsPerThread, lostPixels;

 // a lot of stuff...

 void Start() {

    // lots of other stuff...

    pixelsPerThread = texture.height / threadsToUse;
    lostPixels = texture.height % threadsToUse;
 }

 void Update() {
    if (threadsStarted == 0) {

       // some other stuff...

       threadsCompleted = 0;
       for (int i = 0; i < threadsToUse; i++) {            
          ParameterizedThreadStart pts = new ParameterizedThreadStart(ThreadedColorCopy);
          Thread workerForOneRow = new System.Threading.Thread(pts);
          workerForOneRow.Start(i);
          threadsStarted++;
       }
    }
    else if (threadsCompleted == threadsToUse) {            
       threadsStarted = 0;
       texture.SetPixels(dest);
       texture.Apply();
    }
 }

 private void ThreadedColorCopy(object threadParamsVar) {
    int i = (int)threadParamsVar;
    int fromY = i * (pixelsPerThread);
    int toY = ((i + 1) * pixelsPerThread) - 1;

    if (i == threadsToUse - 1) {
       toY += lostPixels;
    }

    Debug.Log("Thread " + threadParams.threadId + " - from " + fromY + " to " + toY);

    for (int y = fromY; y <= toY; y++) {
       for (int x = textureWidth - 1; x >= 0; x--) {
          int sourceIndex = (y * texture.width) + x;
          dest[sourceIndex].r = source[sourceIndex].r;
          dest[sourceIndex].g = source[sourceIndex].g;
          dest[sourceIndex].b = source[sourceIndex].b;
       }
    }
    threadsCompleted++;
 }

:)

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image SinisterRainbow · Jul 08, 2013 at 03:50 PM 0
Share

great stuff. Thumbed.

avatar image Eugenio · Jul 08, 2013 at 05:11 PM 0
Share

thanks man :)

avatar image mhtraylor · Jul 08, 2013 at 11:34 PM 1
Share

Just thought I would mention F# in connection to the above solution. I've been incorporating it more and more these days in my Unity projects, especially in regards to parallel and asynchronous tasks.

Not necessarily right for every project, but might be something you are interested in if you are doing a lot of concurrency work. Something similar to the above might go like so:

 let copy len src dst = 
         Async.Parallel [ for i in 0..len..(Array.length src) - len -> 
                             async { do Array.blit src i dst i len } ]

...where len would be the chunk size of source Color array you wished to copy. Thread count would be deter$$anonymous$$ed by source length / chunk size.

avatar image Eugenio · Jul 09, 2013 at 09:55 AM 0
Share

Cool. I will definitely give it a go !!

Thanks for sharing :)

avatar image
0

Answer by Sisso · Jul 05, 2013 at 05:24 PM

I dont have 100% sure, but I think that you can.

You can not access any unity3d stuff outside of main thread because unity is not thread safe, but you are free to use many threads do you like.

You can read some data in unity main thread, move it to a indenpendent type like byte[], instantiate a new thread to process the bytes, when it finished, you use the main thread to read the byte[] and update your data.

The project AStarpathfind do some stuff like that.

http://www.arongranberg.com/astar/docs/index.php

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Eugenio · Jul 08, 2013 at 09:29 AM 0
Share

Thanks man, I'll take a look and eventually I'll post my solution here. :)

avatar image
0

Answer by ZJP · May 11, 2017 at 03:15 PM

Have a look here : https://forum.unity3d.com/threads/c-optimized-and-advanced-classic-threads-for-unity-option-with-setthreadaffinitymask.463307/

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

22 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Alternative for semaphores in Unity? 2 Answers

Jobhandle.IsCompleted == true even if job was not scheduled. 1 Answer

How to warm-up job threads 0 Answers

Mutex on Linux 0 Answers

For loop going based off of Time.deltatime? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges