Results 1 to 8 of 8

Thread: Win32 client isn't really idle

  1. #1
    Senior Member
    Join Date
    Dec 2002
    Location
    Madrid, Spain
    Posts
    132

    Win32 client isn't really idle

    I've done a little research about the idle problem. Althought Windows task manager shows sb.exe as having the lowest priority, that's not true.
    I discovered that SB client's "idle" setting equals to priority=4 in Euler2000 (CPU distribution ~50%). If I run Euler2000 with a lower setting, SB takes all the (free) CPU power. If I run Euler2000 with prority=4, I have the same problems (temporary freezes, client's CPU use climbs to 99%) as I have when I run SB.
    And, funny, if I run Euler2000 with the lowest priority (1, no problems), the task manager show its prority as normal .

  2. #2
    The reason is that both threads and processes have priorities. If you set a process to idle, then its threads get set to priority 4, which should be low enough to cause no noticeable problems usually.

    You can also set thread priority (which is what Euler is doing) which allows you to precisely specify the priority, but it doesn't change the process priority (which is why it still shows as Normal where SB shows Idle).

  3. #3
    Senior Member
    Join Date
    Dec 2002
    Location
    Madrid, Spain
    Posts
    132
    Originally posted by Hawk
    The reason is that both threads and processes have priorities. If you set a process to idle, then its threads get set to priority 4, which should be low enough to cause no noticeable problems usually.
    4 it's not low enough. For me, idle means lowest priority, and that's 1.

    You can also set thread priority (which is what Euler is doing) which allows you to precisely specify the priority, but it doesn't change the process priority (which is why it still shows as Normal where SB shows Idle).
    I think Euler's way is better and offers more control to the user.

    Thanks!

  4. #4
    The SB process runs at idle. It has always been that way.

    As of version 1, SB DOES set it's computation thread's priority to the lowest possible using standard API calls. Euler must use some undocumented hack to set priority.

    -Louie

  5. #5
    Probably the best way to check ACTUAL priority is with Spy++ or some similar tool. If you do this, you will find that, with SB set to its "Idle" config, the UI thread has a base priority of 4 and the computation thread has a base priority of 2. This corresponds (Microsoft documentation) to a process priority of IDLE_PRIORITY_CLASS and a thread priority of THREAD_PRIORITY_LOWEST. However, THREAD_PRIORITY_LOWEST really just means "2 points below the process class" and it really isn't the "lowest" priority (don't ask me why they called it that...they didn't ask me). There is a "lower than lowest" thread priority: THREAD_PRIORITY_IDLE which is always priority 1 (unless the process has REALTIME priority).

    My guess (can you confirm this, Louie?) is that the config setting is used to set the process priority class and then the computation thread is set to THREAD_PRIORITY_LOWEST. This would at least correspond to what I've seen in the few cases I've looked at.

    If this is the case, you might consider dropping that THREAD_PRIORITY_LOWEST to THREAD_PRIORITY_IDLE only when the config setting is set to idle.

    OTOH, it works great for me as it is...but I'm not running any other DC clients that I need to split time with.

  6. #6
    Thanks MathGuy. I think you're completely right.

    Actually, looking though the code, it appears I consciously decided not to use THREAD_PRIORITY_IDLE back in November when I compiled it:

    SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
    // SetThreadPriority(cfg->worker_thread, THREAD_PRIORITY_IDLE); too low
    SetThreadPriority(cfg->worker_thread, THREAD_PRIORITY_LOWEST);

    I seem to remember getting reports that THREAD_PRIORITY_IDLE yields to the idle thread on WinNT back when I was testing v1. Most DC projects don't run at priority 1 from what I can tell. I know that everything I've ever run with it at idle (I haven't tried Euler2000) shares cycles 1 for 1 with SB as is.

    I'll probably add an option in the next version that warn users they may stop SB completely by setting it to complete idle.


    -Louie

  7. #7
    Senior Member
    Join Date
    Dec 2002
    Location
    Madrid, Spain
    Posts
    132
    Thanks MathGuy and Louie! I think the best solution would be to use by default THREAD_PRIORITY_LOWEST and let the user to choose THREAD_PRIORITY_IDLE.
    Here is the code other clients use for setting priority:

    a) Sum95 (Euler2000)
    Code:
    void SetPriority(HANDLE thread)
    {
    	SetPriorityClass (GetCurrentProcess (),
    		(PRIORITY < 2 || PRIORITY > 6) ?
    			NORMAL_PRIORITY_CLASS :
    			IDLE_PRIORITY_CLASS);
    
    	SetThreadPriority (thread,
    		(PRIORITY == 1) ? THREAD_PRIORITY_IDLE :
    		(PRIORITY == 2 || PRIORITY == 7) ? THREAD_PRIORITY_LOWEST :
    		(PRIORITY == 3 || PRIORITY == 8) ? THREAD_PRIORITY_BELOW_NORMAL :
    		(PRIORITY == 4 || PRIORITY == 9) ? THREAD_PRIORITY_NORMAL :
    		(PRIORITY == 5 || PRIORITY == 10) ? THREAD_PRIORITY_ABOVE_NORMAL :
    		THREAD_PRIORITY_HIGHEST);
    	if (CPU_AFFINITY != 99 && !isWindows95 ())
    		SetThreadAffinityMask (thread, 1 << CPU_AFFINITY);
    }
    b) Distributed.net 20010416
    Code:
      #elif (CLIENT_OS == OS_WIN32)
      {
        static int useidleclass = -1;           // track detection state.
        int threadprio = 0, classprio = 0;
        HANDLE our_thrid = GetCurrentThread();  // Win32 pseudo-handle constant.
    
        if (set_for_thread && (w32ConGetType() & 0xff)=='G') 
        { // crunchers in a 'fat-'GUI client always run at idle prio
          prio = 0;
        }
      
        /*************************** Article ID: Q106253 *******************
                                  process priority class
        THREAD_PRIORITY          Normal, in      Normal, in
                          Idle   Background      Foreground    High    Realtime
        _TIME_CRITICAL     15        15              15         15        31
        _HIGHEST            6         9              11         15        26
        _ABOVE_NORMAL       5         8              10         14        25
        _NORMAL             4         7               9         13        24
        _BELOW_NORMAL       3         6               8         12        23
        _LOWEST             2         5               7         11        22
        _IDLE               1         1               1          1        16
        ********************************************************************/
      
        /* If we want to run with an idle priority *class*, we need to be able
           to set a *thread* priority of _TIME_CRITICAL for the main and 
           window-handler threads, otherwise I/O will be laggy beyond belief.
    
           If we cannot set _TIME_CRITICAL, then we have no choice but to use a 
           NORMAL_PRIO_CLASS. Such is win32 scheduling; stupid, stupid, stupid.
        */
        if (useidleclass == -1) /* haven't selected yet */
        {         
          SetPriorityClass( GetCurrentProcess(), IDLE_PRIORITY_CLASS );
          Sleep(1);
          SetThreadPriority( our_thrid, THREAD_PRIORITY_TIME_CRITICAL);    
          if (GetThreadPriority( our_thrid ) == THREAD_PRIORITY_TIME_CRITICAL)
            useidleclass = 1;
          else
          {
            useidleclass = 0;
            SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS );
            Sleep(1);
          }
          SetThreadPriority( our_thrid, THREAD_PRIORITY_NORMAL );    
        }
    
        if (useidleclass == 1)
        {
          classprio = IDLE_PRIORITY_CLASS;
          if (!set_for_thread) threadprio = THREAD_PRIORITY_TIME_CRITICAL;/* 15 */
          else if (prio >= 7)  threadprio = THREAD_PRIORITY_HIGHEST;      /*  6 */
          else if (prio >= 5)  threadprio = THREAD_PRIORITY_ABOVE_NORMAL; /*  5 */
          else if (prio >= 4)  threadprio = THREAD_PRIORITY_NORMAL;       /*  4 */
          else if (prio >= 3)  threadprio = THREAD_PRIORITY_BELOW_NORMAL; /*  3 */
          else if (prio >= 2)  threadprio = THREAD_PRIORITY_LOWEST;       /*  2 */
          else /* prio < 2 */  threadprio = THREAD_PRIORITY_IDLE;         /*  1 */
        }
        else /* if (useidleclass == 0) */
        {
          classprio = NORMAL_PRIORITY_CLASS;
          if (!set_for_thread) threadprio = THREAD_PRIORITY_NORMAL;       /*  8 */
          else if (prio >= 7)  threadprio = THREAD_PRIORITY_BELOW_NORMAL; /*  6 */
          else if (prio >= 5)  threadprio = THREAD_PRIORITY_LOWEST;       /*  5 */
          else                 threadprio = THREAD_PRIORITY_IDLE;         /*  1 */
        }
        //SetPriorityClass( GetCurrentProcess(), classprio );
        //Sleep(1);
    
        SetThreadPriority( our_thrid, threadprio );
      }

  8. #8
    It would be great if a future client has the abbility to set the priority level (i,e, 1-10) instead of idle, low, below normal, normal)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •