Thread Question

A place to discuss the science of computers and programs, from algorithms to computability.

Formal proofs preferred.

Moderators: phlip, Moderators General, Prelates

snow5379
Posts: 247
Joined: Tue Apr 12, 2011 6:06 pm UTC

Thread Question

Postby snow5379 » Wed Oct 17, 2012 10:34 am UTC

Is there any reason not to start a thousand threads? I ask this because I have a bunch of objects that do things. I can have one thread that calls all of them or give each one their own thread.

User avatar
headprogrammingczar
Posts: 3072
Joined: Mon Oct 22, 2007 5:28 pm UTC
Location: Beaming you up

Re: Thread Question

Postby headprogrammingczar » Wed Oct 17, 2012 11:18 am UTC

There's different kinds of threads. You wouldn't want to make a thousand OS-level threads unless you had that many CPUs to run them on.

Something like GHC might provide its own lightweight thread abstraction, which is totally independent of OS threads. You can create thousands of lightweight threads, and they will get shuffled between OS threads with much less overhead. It's not uncommon in Haskell to write an "embarassingly threaded" program, like a server that makes a thread for every incoming connection.

Since you mention "objects", I assume you are using Java? You wouldn't make thousands of threads in Java, but more likely use a thread pool that you can pass objects to.
<quintopia> You're not crazy. you're the goddamn headprogrammingspock!
<Weeks> You're the goddamn headprogrammingspock!
<Cheese> I love you

LikwidCirkel
Posts: 169
Joined: Thu Nov 08, 2007 8:56 pm UTC
Location: on this forum (duh)
Contact:

Re: Thread Question

Postby LikwidCirkel » Wed Oct 17, 2012 3:54 pm UTC

Some thread implementations have a ton of scheduling and memory overhead, so it's generally best to not use more than available execution cores if you have limited computing resources.

Use a thread pool or event-driven I/O or some other kind of construct to reduce overhead.

I have to admit, one of my programming pet peeves is naive use of multi-threading where it really shouldn't be done.

Threads serve two purposes, and a third, sort of naive purpose.
1) Make the code easier to understand and conceptualize (e.g., multi-client or multi-track playback where each stream is a thread)
2) Actually increase performance by utilizing execution cores in parallel
3) It's sometimes the only (easy) way to deal with I/O from multiple sources.

I generally believe that if a platform forces you to do 3, then it is a limited and flawed platform/OS.

Alternate approaches:
Use a thread pool and start/stop them with some kind of argument with events.
Use a single thread (or just a few) and make it _purely_ event-driven (my favorite). On a single execution core, this will pretty much always use less memory, perform faster, and be more scalable than using multiple threads.

The problem is that there is no nice portable interface for event multiplexing. On Linux you have epoll, MAC/BSD you have kqueue, and Windows you have overlapped I/O and WaitForMultipleObjects. All platforms have select(), but it's slow and not very scalable. Some libraries like libevent can wrap all of this into a portable interface. You can do similar things through just a few threads and a mutex/condvar protecting some task-status variables.

Sorry for the rant. I'm just becoming a crufty old rigid embedded developer and I'm used to dealing with very limited resources. Single-threaded event-driven code is how I like things to be, and it's generally harder to do properly than writing multi-threaded code.

snow5379
Posts: 247
Joined: Tue Apr 12, 2011 6:06 pm UTC

Re: Thread Question

Postby snow5379 » Wed Oct 17, 2012 7:01 pm UTC

It's good to be like that. I've started on a big solo project and I'm about a month into planning.

It's been a dream of mine ever since I was 18 or so to create a game and I think at this point in my life I have enough coding experience to give it a shot. I'm just trying to learn a bit more before going all in. And... yes I'm coding in Java.

Another thread question: does thread priority matter at all? I have a few loops and to prevent them from using 100% of my CPU I have them sleep every so often... but that just feels dirty. For example here's a class I coded that basically just draws to the screen:

Code: Select all

package files;

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

class frame extends JFrame implements Runnable
{
   frame(String a,BufferedImage b,int c,int d)
   {
      setTitle(a);
      setIconImage(b);
      setSize(c,d);
      setLayout(null);
      setLocationRelativeTo(null);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setVisible(true);
      new Thread(this).start();
   }

   public void run()
   {
      JLabel a=new JLabel();
      add(a);

      while(true)
      {
         BufferedImage b=new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_ARGB);
         draw(b.getGraphics());
         a.setBounds(0,0,getWidth(),getHeight());
         a.setIcon(new ImageIcon(b));
         try{Thread.sleep(10);}catch(Exception exception){}
      }
   }

   void draw(Graphics a){}
}


Is there any way I can improve this code? I don't really care about a high FPS. I just don't want to tie up too many resources and sleeping seems a bit crude.

snow5379
Posts: 247
Joined: Tue Apr 12, 2011 6:06 pm UTC

Re: Thread Question

Postby snow5379 » Wed Oct 17, 2012 9:25 pm UTC

Another question (again about threads):

I'm going to have an online mode for my game and at the moment I create a thread for each connecting client. I can't figure out any other way to do it because if I don't make threads the server locks up while waiting for a connection.

How do you deal with that? Do you set a timer for each read? Do you check if the output stream has data? I haven't coded much yet because I'm still in the planning stages and want a solid framework before I really begin.

EvanED
Posts: 4331
Joined: Mon Aug 07, 2006 6:28 am UTC
Location: Madison, WI
Contact:

Re: Thread Question

Postby EvanED » Wed Oct 17, 2012 10:02 pm UTC

That's one of the "common" uses of threads, but you can also do it using select() (not sure what it's called on Windows). Basically, select is a function that will block until some file/socket has data available (and tell you which one), so then you can go and read from it, serve the request, then call select again.

One other common use for threads: running background tasks in a GUI program so you can keep the GUI responsive. It's not the only way to do that, but I do think that threads are often one of the easiest ways to do so.

User avatar
WanderingLinguist
Posts: 237
Joined: Tue May 22, 2012 5:14 pm UTC
Location: Seoul
Contact:

Re: Thread Question

Postby WanderingLinguist » Wed Oct 17, 2012 10:57 pm UTC

snow5379 wrote:Is there any way I can improve this code? I don't really care about a high FPS. I just don't want to tie up too many resources and sleeping seems a bit crude.


Sleeping is generally the right way to do it. Changing thread priorities can get messy quickly.

A good general guideline is to change thread priorities only if
  • You need to do something time critical or real-time. For example, if you need to output an audio stream and dont want it to stutter because some other thread was running and it couldn't write the audio output in a timely manner. This generally only happens in really low-latency applications (normally you just fill a buffer and let a lower-level component handle this for you).
  • You need to do something in the background and you don't care if it's stops for really long periods of time, but don't want it to interfere with foreground tasks. For example, indexing the whole filesystem or something.

Even in this cases (especially the real-time case) you'll still either sleep or block in some way until there's something to do.

Basically, you want the thread to do the minimum it needs to do, and when it's done, block (either on input, on a synchronization primitive, or by sleeping) until there's something new to be done. Messing with thread priorities should be reserved for very special cases.

From a game standpoint, a very common model is to save the time when you start drawing (something like System.nanoTime() is good for that, because it doesn't change if the user adjusts the system clock), then draw the frame. Before you start drawing the next frame, check the time again to determine how much time has elapsed since you drew your last frame. Based on that, and your target frame rate, you can determine how long to sleep. For example, let's say you're targeting 30fps, but it took 5ms to draw the last frame. That means you should sleep for 25ms before drawing the next frame. Keep in mind the sleep could terminate early (you could get an interrupted exception) so you should handle that appropriately (check exit conditions, etc., and if there's nothing to do, check the new time and sleep again).

Keep in mind that if drawing takes too long, you want the frame rate to drop rather than the game to slow down (usually), so having your game logic (moving game objects around) separate from your drawing code is good. The first thing to do is check how much time has elapsed and if necessary call your game logic function multiple times to catch it up the present, then call your drawing function.

This approach is good because it means that if you have more going on (more enemies on the screen, just for example) your game will still run at the same rate: It will just use more processor resources (until they max out, at which point it will start dropping frames, but the timing will remain consistent).

So, yes, sleeping is correct -- just make sure you use it right.

The server question has already been answered (multiple threads, or use select or something). Back when multi-threading was less common, for the client-side of the connection, it was sometimes easier to put the socket code into the game loop. In this case, before running the game logic, I'd run a non-blocking select to see if any data was available to be read on any socket, and if not, move on to run the game logic and then draw the game state. Threading makes this easier (or harder, depending on how you do it).

LikwidCirkel
Posts: 169
Joined: Thu Nov 08, 2007 8:56 pm UTC
Location: on this forum (duh)
Contact:

Re: Thread Question

Postby LikwidCirkel » Thu Oct 18, 2012 2:20 pm UTC

snow5379 wrote:I'm going to have an online mode for my game and at the moment I create a thread for each connecting client. I can't figure out any other way to do it because if I don't make threads the server locks up while waiting for a connection.

How do you deal with that? Do you set a timer for each read? Do you check if the output stream has data? I haven't coded much yet because I'm still in the planning stages and want a solid framework before I really begin.


EvanED wrote:That's one of the "common" uses of threads, but you can also do it using select() (not sure what it's called on Windows). Basically, select is a function that will block until some file/socket has data available (and tell you which one), so then you can go and read from it, serve the request, then call select again.


Select does exist on pretty much all platforms, including Java through the Selector class. I'd recommend looking into this, because I consider it to be the proper way to handle multiple clients, and should perform significantly better with respect to memory usage if there are many clients. Using threads is the easy/beginner way. Select is sort of dated, slow and non-scalable, but it IS mostly portable. I don't know if there is anything better to use in Java though, so I wouldn't worry about that. If it was C, I'd say to use libevent, which is a portable wrapper for epoll/kqueue/IOCP (improved OS-specific select-like mechanisms).

As far as sleeping regularly in the rendering thread, I don't generally like doing this, but there are reasons you might want to. Keep in mind that there is seldom any point sleeping LESS than 17ms, because this is the screen refresh interval on most modern monitors. Also, there is no point of rendering if nothing has changed, so I'd look into a signalling mechanism from other threads. You could use a mutex/condvar construct, or introduce a "dirty" variable which will get checked before the render operation, so you can skip the refresh if nothing needs to change. If you use double buffering and only render when something actually changes, some of this should become easier to deal with. This allows multiple tasks to work on a buffer which gets flipped to the screen only at refresh intervals, which is generally what you want for smooth rendering.

As a disclaimer, I am not a Java expert.... I'm mostly drawing on experience from other platforms.

DaveInsurgent
Posts: 207
Joined: Thu May 19, 2011 4:28 pm UTC
Location: Waterloo, Ontario

Re: Thread Question

Postby DaveInsurgent » Thu Oct 18, 2012 10:15 pm UTC

You could use a mutex/condvar construct, or introduce a "dirty" variable which will get checked before the render operation,


Does anybody actually do this kind of retained mode rendering in a real game engine? I kind of doubt it. Odds are that something has changed, and attempting to signal that from every possible object capable of changing seems to be to be very, very inefficient.

User avatar
WanderingLinguist
Posts: 237
Joined: Tue May 22, 2012 5:14 pm UTC
Location: Seoul
Contact:

Re: Thread Question

Postby WanderingLinguist » Thu Oct 18, 2012 10:51 pm UTC

LikwidCirkel wrote:As far as sleeping regularly in the rendering thread, I don't generally like doing this, but there are reasons you might want to. Keep in mind that there is seldom any point sleeping LESS than 17ms, because this is the screen refresh interval on most modern monitors.


What alternative would your propose to sleeping? If it's not time to draw the next frame yet, then... what do you do?

Also, you might very well sleep less than 17ms. For example, let's say it takes 30ms to render the frame, and you are aiming for 30 frames per second. You'll want to sleep just 3ms in that case. You can start drawing the next frame during the refresh interval. Also, 17ms is very high. Even older CRT monitors had higher refresh rates. I generally had mine set at 72hz or higher (less than that gave me headaches and, as I seem to recall, has been show to cause increased eye strain). Modern LCD monitors are usually locked at around 60fps, which is a little less than 17ms, but some go as high as 600. Android devices running ICS or later update the screen 60 times per second.

Most modern platforms that support high-performance graphics have a way of syncing to the screen refresh interval. So generally, you want to time your rendering to that if possible (if not, you'll occasionally miss an update, which makes things look less smooth even if you're still getting close to 60 frames per second). Even on old CRT monitors, timing to the vertical refresh interval was important to avoid "tearing".

So yeah, I think sleeping based on how long it took to prepare the frame is a good general approach. For a really smooth experience (if your rendering process is fast enough), you'll want to separate the rendering thread from the presentation thread (in other words, your rendering thread prepares the buffer for display, and the presentation thread displays it asynchronously based on the screen refresh time). If you're running at around 60fps, it's no problem to render a frame ahead (have an extra buffer) so you can be preparing the next frame already. If you've rendered ahead more than two frames, the rendering thread can block until a buffer is consumed. (Rendering ahead more than two 60fps frames in a game is generally not a good idea because it will hurt responsiveness to user input).

LikwidCirkel
Posts: 169
Joined: Thu Nov 08, 2007 8:56 pm UTC
Location: on this forum (duh)
Contact:

Re: Thread Question

Postby LikwidCirkel » Fri Oct 19, 2012 12:38 am UTC

This is all true, and the solution for smoothness is to use timer objects in addition multiple buffers as described by WanderingLinguist here. Timer objects will wake at regular intervals.

This explains it pretty well I think. Check out the example code too.
http://gpsnippets.blogspot.ca/2010/10/how-to-use-bufferstrategy-in-java.html

WanderingLinguist wrote:Most modern platforms that support high-performance graphics have a way of syncing to the screen refresh interval.


This kind of thing is super useful I think if you can actually find a way to do it... it's probably how all classic video games work. I couldn't find a java way, but it shouldn't be too important if you just aim for 60FPS or a bit higher with a timer. Hardly anyone can see the difference anyway. I'm just used to cheap LCD monitors I guess - they're always at 60Hz.

All helpful advice! Gets people thinking about these things.

User avatar
WanderingLinguist
Posts: 237
Joined: Tue May 22, 2012 5:14 pm UTC
Location: Seoul
Contact:

Re: Thread Question

Postby WanderingLinguist » Fri Oct 19, 2012 6:56 am UTC

LikwidCirkel wrote:
WanderingLinguist wrote:Most modern platforms that support high-performance graphics have a way of syncing to the screen refresh interval.


This kind of thing is super useful I think if you can actually find a way to do it... it's probably how all classic video games work. I couldn't find a java way, but it shouldn't be too important if you just aim for 60FPS or a bit higher with a timer. Hardly anyone can see the difference anyway. I'm just used to cheap LCD monitors I guess - they're always at 60Hz.

I don't know if there's a standard way to do it in desktop Java or not. I think some newer versions of EGL might expose that functionality in a standard way, but that's only useful if you can use EGL. I do a lot of development on Android, and from ICS onward everything is synced to the screen refresh interval (as I understand it, even incoming touch events are re-timed so that processing completes in a consistent manner relative to the original event).

And I beg to differ: You may not see the difference between 60fps and 30fps if you're not looking at the side-by-side, but you WILL see the difference between 60fps displayed steadily, and 60fps that skips a frame (dropping to 30fps) once in a while. Especially in certain animations (scrolling lists are a big one). Users may not always consciously notice the difference, but they might very well have a sense of instability about the application due to it.

As a result, a lot of Android developers these days aim for 60fps updates to the screen.

This is all true, and the solution for smoothness is to use timer objects in addition multiple buffers as described by WanderingLinguist here. Timer objects will wake at regular intervals.

This explains it pretty well I think. Check out the example code too.
http://gpsnippets.blogspot.ca/2010/10/h ... -java.html


I don't see where timers appear in the example. I'd still argue that sleep is a better approach in some cases. For example, what if the timer fires again before you're done processing the first one? Does it simply skip the frame, or does it cue up the event? (Both of these are extremely bad for games). The only useful approach would be to skip the event and then inform you (in the next event) that one was skipped. But this is getting complicated, and you might as well sleep.

Also, if you're updating your game state too, you might need to run several frames of game-state update but only one frame of display update. If you're handling the timing yourself (with sleep) you can control that (if you have time to sleep for display, you can use it to catch up the game state if it's behind, just for example). In almost every case where I started out using timers like this, I ended up switching to "sleep" each time to better manage the timing.

mousewiz
Posts: 107
Joined: Wed Oct 26, 2011 6:50 pm UTC

Re: Thread Question

Postby mousewiz » Sun Oct 21, 2012 7:18 pm UTC

LikwidCirkel wrote:Select does exist on pretty much all platforms, including Java through the Selector class. I'd recommend looking into this, because I consider it to be the proper way to handle multiple clients, and should perform significantly better with respect to memory usage if there are many clients. Using threads is the easy/beginner way. Select is sort of dated, slow and non-scalable, but it IS mostly portable. I don't know if there is anything better to use in Java though, so I wouldn't worry about that. If it was C, I'd say to use libevent, which is a portable wrapper for epoll/kqueue/IOCP (improved OS-specific select-like mechanisms).


Actually the "select" in Java 1.6+ doesn't actually have to correspond to the C select. In the case of Linux 2.6 or newer it uses epoll. You can also override something or other somewhere to create your own selector provider in case of your OS providing something nice and Java not knowing about it, though I haven't had to do that.

http://docs.oracle.com/javase/6/docs/technotes/guides/io/enhancements.html wrote:A new java.nio.channels.SelectorProvider implementation that is based on the Linux epoll event notification facility is included. The epoll facility is available in the Linux 2.6, and newer, kernels. The new epoll-based SelectorProvider implementation is more scalable than the traditional poll-based SelectorProvider implementation when there are thousands of SelectableChannels registered with a Selector. The new SelectorProvider implementation will be used by default when the 2.6 kernel is detected. The poll-based SelectorProvider will be used when a pre-2.6 kernel is detected.


Return to “Computer Science”

Who is online

Users browsing this forum: No registered users and 4 guests