Tech Off Thread

14 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Single-threaded assumptions in older software

Back to Forum: Tech Off
  • User profile image
    W3bbo

    I was wondering about old multithreaded software from 1990 to the early-00s that were developed for and primarily run on single-threaded hardware. Because there was only a single hardware thread, would it have been reasonable for a developer to not include any real kind of synchronisation, or made any other 'mistakes' or bugs that would otherwise have gone undetected so long as only one thread of the application is run at a time.... or is the protection provided by basic synchronisation constructs (locks and mutexes, et al.) sufficient?

    Now that multi-threaded hardware is thoroughly embedded in the market, are there any cases of these kinds of bugs happening? And is the "Set affinity" option in Task Manager enough to give the process an operating environment similar enough to single-threaded hardware from the mid-1990s?

  • User profile image
    AndyC

    @W3bbo: Kind of. You couldn't include no synchronisation at all, because that would cause issues even with simulated threading. But there are whole classes of race condition that are considerably less likely to occur when on a uniprocessor system (and a few that can't happen then). When run on a true multiprocessing system (especially as core count goes up) these wierd bugs can raise there head quite quickly.

    Used to see this quite often running dual-processor NT4 boxes (which in the wider world were a bit of a rarity), the fix indeed just being to set affinity on applications that suffered it. Not seen that sort of thing for years though, presuambly because multiprocessor boxes have been used by devs for some time now.

     

  • User profile image
    wkempf

    Sorry, your terminology is bugging me. There's no "multi-threaded hardware". Threads are a construct of the OS, not the hardware (unless you count hyper-threading). What you're really asking is whether there's a difference in how threads behave between single processor machines and multi-processor machines.

    AndyC has this right. When a program has multiple threads each thread "logically" runs concurrently, even if there's a single processor. I say "logically" and put it in quotes, because in reality the code does not run concurrently as there's a single processor for it to run on, but since each thread can be interrupted by other threads at any point in time there's still a form of concurrency going on. Therefore, it's not possible (beyond lock-free algorithms) to write multi-threaded applications on a single processor machine without employing synchronization constructs. However, since the threads aren't physically running concurrently some race conditions may never or rarely result in percieved errors. This is why, in those days, serious multi-threading work was done with, or at least tested on, more expensive multi-processor machines, even though the application would usually be run on a single processor machine.

  • User profile image
    W3bbo

    , wkempf wrote

    Sorry, your terminology is bugging me. There's no "multi-threaded hardware". Threads are a construct of the OS, not the hardware (unless you count hyper-threading). What you're really asking is whether there's a difference in how threads behave between single processor machines and multi-processor machines.

    There is. Multiprocessing is not the same thing as Multithreading, and threads do exist in hardware.

    From wikipedia:

    Multithreading computers have hardware support to efficiently execute multiple threads. These are distinguished from multiprocessing systems (such as multi-core systems) in that the threads have to share the resources of a single core: the computing units, the CPU caches and the translation lookaside buffer (TLB).

    [quote]However, since the threads aren't physically running concurrently some race conditions may never or rarely result in percieved errors.

    That's what I'm asking about; how common (and what kinds of bugs/problems) these issues are. Given a preemptive scheduler could cause a context-switch at any point of execution in a multi-threead program it makes sense to exclusively-lock resources as you would whether or not the hardware supported concurrent threads. So what problems are they?

  • User profile image
    wkempf

    @W3bbo: Trust me, I know the difference between multi-processing and multi-threading, both of which, BTW, are done by the OS and not the hardware. What Wikipedia is referring to is hardware support for optimizing the context switching logic required, which is related, but not the same thing. The hardware is still NOT multi-threaded (again, with hyper threading being a complex concept to pin down in this categorization).

    The problems that exist in single processing systems have to do with race conditions. Put simply, when you have a race condition you have some probability of shared state access not occuring in the order in which you'd expect. The probability will vary based on numerous factors, many of which you can't really account for, but one of which happens to be whether or not threads actually run concurrently (which increases the probability of the race failing). IOW, the bugs/problems exist in the code regardless, but the race may never (or rarely) manifest as an error at run time when run on a single processor machine, but may manifest almost immediately and every time when run on a multi-processor machine. There's a reason these are comically referred to as Heisenbugs, and you can basically imagine multiple processors as being multiple "observers" that cause a larger change in the operations characteristics Wink.

    That said, there's not really a "class" of bugs/problems that you could consider unique to single processor machines. Whether or not a given race condition is noticably more likely to occur on a single processor isn't something you can easily classify, and it's a bug regardless of the architecture it's run on. "Never (or rarely)" means it will happen the minute it's run in production and is most critical that it not fail. Double-Checked locking is a classic example of just this topic. The pattern was considered state of the art and full proof for a very long time, used in lots of critical code running with high frequency on millions of computers until it finally failed in production and the experts were able to figure out why. (This topic also plays into the discussion of the hardware optimizations provided for threading purposes, as the memory model employed determines whether or not there's a race condition here.)

  • User profile image
    AndyC

    If you're looking for a more concrete example, the following code will almost certainly work on a uniprocessor system as incrementing the shared variable is exceptionally unlikely to take the entire quanta:

    Sleep(1);  // relinquish the CPU so when we return we have
                   // our full quanta available
    tmp = shared_var;
    tmp += 1;
    shared_var = tmp;

     

    But is extremely likely to fail on multiprocessor (or multicore) systems, since there is a higher likelyhood of two threads acting simultaneously. Or it might not, if the compiler goes and uses one of them fancy interlocked memory incrementing instructions, but by that point you're well into the realms of implementation specific.

    The majority of multithreading bugs are probably just as common to encounter on a uniprocessor system though. Doubly so if it's a production deployment that's never failed in test!

    And I have to agree with Dr Herbie, your use of terminology is a bit confusing.

  • User profile image
    wkempf

    Dr Herbie? I don't see that he replied to this thread? Sorry, I'm a bit confused who you're talking to and what you're saying in that last sentence. Smiley

  • User profile image
    AndyC

    @wkempf: I'm old. i remember when this was all field's y'know...

    Tongue Out

  • User profile image
    wkempf

    I'm old too. Maybe that's why I'm confused? Trying to understand, did you mean me instead of Dr. Herbie? After reading the sentence again, it might make sense that way. Or did I just miss something entirely in a related thread?

    Edit: The reason I'm trying to figure this out, is I'm not sure who you're saying was using confusing terminology, and I just want to make sure it wasn't me.

  • User profile image
    AndyC

    @wkempf: That bit where I wrote Dr Herbie, that was supposed to say wkempf. Twas W3bbo's terminology that was confusing, yours is fine. I could edit the original, so you just sound crazy, but I think I'll leave my insanitys present.

  • User profile image
    W3bbo

    @W3bbo: Trust me, I know the difference between multi-processing and multi-threading, both of which, BTW, are done by the OS and not the hardware. What Wikipedia is referring to is hardware support for optimizing the context switching logic required, which is related, but not the same thing. The hardware is still NOT multi-threaded (again, with hyper threading being a complex concept to pin down in this categorization).

    I'll admit that "HyperThreading CPUs" throw me off, as they're capable of executing two threads simultaneously (when both threads are using different components of the CPU). But what about the UltraSPARC T1 processor? WP describes it as "UltraSPARC T1 is its first microprocessor that is both multicore and multithreaded. The processor is available with four, six or eight CPU cores, each core able to handle four threads concurrently".

  • User profile image
    AndyC

    , W3bbo wrote

    *snip*

     WP describes it as "UltraSPARC T1 is its first microprocessor that is both multicore and multithreaded.

    That's what's technically referred to as 'marketing b*llsh*t'

    The Sparc T1, like a Hyperthreading x86 device effectively 'fakes' additional logical processors within each core. It then internally handles scheduling of the instructions so that it can maximise throughput on that core (i.e. running a different 'thread' during a cache miss, or making use of an otherwise redundant ALU).

  • User profile image
    PerfectPhase

    @W3bbo: One of the better descriptions of Hyperthreading I've found.

    http://software.intel.com/en-us/articles/introduction-to-hyper-threading-technology/

    Anyway, back to the original question, back in the day when our dev's used to have single core machines, and only the test department had dual proc or above machines, we often used to find deadlocks/races in our code duing testing, so it wouldn't suprise me if you would find issues with old code if run on moderen machines.

  • User profile image
    teslaBytes

    Hmm, a sparc processor is designed to process string data, it's a string supuer computer, make your sreams all string type, and the processor will, multi process them faster then lightning...  So I heard while working at SUN.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.