Here are the results I ran your sample program on one core and dualcore 
machines:

One Core:
run with Update Less: Worker0: on average takes 3750 miliseconds
                      Worker0 + Worker1: on average takes 5980 ms

Dual Core:
run with Update Less: Worker0: on average takes 4000 ms
                      Worker0 + Worker1: on average takes 7532 ms.

I looked at the task manager performance when running on dualcore, the two 
cores were not processing simultaneously.

I would like to take the advantage of the dualcore. What is the approach I 
should take to program one core doing calculation while the other core 
displaying results?

Thanks,



//////////////////////////////////////////////////////
// Threading demo
// fltk-config --compile simple-thread-demo.cxx
//

#include <stdlib.h>
//#include <unistd.h>
#include <math.h>
#include <time.h>

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Value_Output.H>
#include <FL/fl_message.H>

#ifdef WIN32
#  include <windows.h>
#  include <process.h>
#  define THREAD HANDLE
#  define wait_here(x) Sleep(x)
#  define SCHED_YIELD Sleep(0)
#else /* for *nix and OSX */
#  include <pthread.h>
#  include <sched.h> // maybe necessary for sched_yield ?
#  define THREAD pthread_t
#  define PTHREAD_WRAPPER 1
#  define wait_here(x) usleep((x)*1000)
#  define SCHED_YIELD sched_yield()
#endif

//#define GUI_REFRESH_THD 987
#define GUI_REFRESH_THD 493

clock_t startTime0, endTime0, startTime1, endTime1;

static Fl_Double_Window *main_win=(Fl_Double_Window *)0;

static Fl_Button *work_0=(Fl_Button *)0;
static Fl_Button *work_1=(Fl_Button *)0;
static Fl_Button *yeild_bt=(Fl_Button *)0;
static Fl_Button *reduced_update=(Fl_Button *)0;
static Fl_Button *quit_bt=(Fl_Button *)0;

static Fl_Value_Output *out[2];
/* Should the worker threads yield periodically or not? */
static int use_yield = 0;
// use this to make the GUI update less often
static int reduce_refresh_rate = 0;

// Use to signal child threads to terminate... It's a cheap IPC hack...
static int keep_running = -1;
static int thread_active[2]; // one per worker...

/* Wrapper to start the worker thread */
THREAD make_thread (void (*task)(void *), void *arg)
{
        int res;

#ifdef WIN32
        res = _beginthread(task, 0, arg);
        return (THREAD)res;

#else // linux, OSX and other unix systems
        pthread_t thread;
        res = pthread_create(&thread, NULL, (void*)task, arg);
        if (res == 0)
                return thread;
        else
            return (THREAD)0;

#endif
}

// Send the updated value to the GUI - this may be sloooowwwww....
static void display_value(int id, double val) {
        Fl::lock();                     // avoid conflicting calls
        out[id]->value(val);    // update the GUI value
        Fl::awake();                    // tell the GUI thread that something 
maybechanged
        Fl::unlock();                   // allow other threads to access FLTK 
again
}

/* This is the worker thread - it chews up ALL the CPU that it is given
*/
void test_thread(void *arg)
{
        int id = (int)arg;
        double dr = 0.0;

        int ii = 2000;

        if (id == 0)
                startTime0 = clock();
        else
                startTime1 = clock();

        while ((keep_running) && (thread_active[id]) && ii > 0)
        {
                // do something slow here
                for (int j = 0; j < 6789; j++)
                {
                        double d = (double)(j+1);
                        dr = log(d);
                        if(reduce_refresh_rate == 0){
                                // update on every iteration - verySLOW!
                                // If you update on every iteration,then what 
tends
                                // to happen is that the CPU the GUIthread is 
running
                                // on gets pegged, and that become therate 
determining
                                // stage.
                                // So, usually it is better to onlyupdate the 
GUI
                                // periodically...
                                display_value(id, dr);
                        }
                        else {
                                static int iter = GUI_REFRESH_THD;
                                if(iter < 0) {
                                        // update periodically - less slow!
                                        display_value(id, dr);
                                        iter = GUI_REFRESH_THD;
                                }
                                iter--;
                        }
                }
                /* On some systems, particularly single-cpu ones,throwing in the
                 * occasional voluntary worker yield will make the GUI thread 
seem
                 * more responsive. */
                if(use_yield) SCHED_YIELD;
                ii--;
        }
        if (id == 0)
        {
                endTime0 = clock();
                dr = (double)(endTime0 - startTime0);
                display_value(id, dr);
        }
        else
        {
                /*endTime1 = clock();
                dr = (double)(endTime1 - startTime1);
                display_value(id, dr);*/

                //display total time running on both threads
                dr = (double)(endTime1 - startTime0);
                display_value(id, dr);

        }

        return;
}       // END of test_thread(void *arg)

static void do_start(int state, int id) {
        if(state) { // start the worker thread
                thread_active[id] = 1;
                make_thread(test_thread, (void *)id);
        }
        else { // terminate the worker thread
                thread_active[id] = 0; // the worker will see this and exit
        }
}

static void cb_work_0(Fl_Button* o, void*) {
        int state = o->value();
        do_start(state, 0);
}

static void cb_work_1(Fl_Button* o, void*) {
        int state = o->value();
        do_start(state, 1);
}

static void cb_yeild_bt(Fl_Button* o, void*) {
        use_yield = (int)o->value();
}

static void cb_reduce_bt(Fl_Button* o, void*) {
        reduce_refresh_rate = (int)o->value();
}

static void cb_quit_bt(Fl_Button*, void*) {
        main_win->hide(); // close the GUI
        keep_running = 0; // ask the workers to expire
}

int main(int argc, char **argv) {
        // ensure thread support is enabled...
        Fl::lock();

        // now build the GUI
        main_win = new Fl_Double_Window(322, 209, "Thread control");
        main_win->begin();

        work_0 = new Fl_Button(25, 18, 70, 27, "Worker 0");
        work_0->tooltip("Start woker thread 0");
        work_0->type(FL_TOGGLE_BUTTON);
        work_0->callback((Fl_Callback*)cb_work_0);

        work_1 = new Fl_Button(135, 18, 70, 27, "Worker 1");
        work_1->tooltip("Start woker thread 1");
        work_1->type(FL_TOGGLE_BUTTON);
        work_1->callback((Fl_Callback*)cb_work_1);

        out[0] = new Fl_Value_Output(25, 58, 70, 24);
        out[1] = new Fl_Value_Output(135, 58, 70, 24);

        yeild_bt = new Fl_Button(25, 163, 70, 27, "With Yeild");
        yeild_bt->tooltip("Cause worker threads to yeild periodically");
        yeild_bt->type(FL_TOGGLE_BUTTON);
        yeild_bt->callback((Fl_Callback*)cb_yeild_bt);

        reduced_update = new Fl_Button(135, 163, 80, 27, "Update Less");
        reduced_update->tooltip("Update the GUI less often");
        reduced_update->type(FL_TOGGLE_BUTTON);
        reduced_update->callback((Fl_Callback*)cb_reduce_bt);

        quit_bt = new Fl_Button(240, 163, 70, 27, "Quit");
        quit_bt->tooltip("Doh!");
        quit_bt->callback((Fl_Callback*)cb_quit_bt);

        main_win->end();

//      char msg[1000];
//      sprintf(msg,"GUI_REFRESH_THD = %d",GUI_REFRESH_THD);
//      fl_message(msg);

        // show the GUI
        main_win->show(argc, argv);

        // start the event loop
        return Fl::run();
}
/* end of file */

// SELEX Galileo LtdRegistered Office:
// Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL
// A company registered in England & Wales. Company no. 02426132


_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk

Reply via email to