Page 1 of 2

wxThread / newbie

Posted: Thu Feb 13, 2020 10:12 pm
by art-ganseforth
Hello,

some newbie-questions concerning multithreading...

I have a script-interpreter-class (clsParser) with severai. nested instances. Most script-executions are triggert by events or parent-instances. Now i want to deligate some of these calls to parallel threads. Therefore i created a small class (clsParserThread) derived from wxThread, that is instanced like this: clsParserThread(clsParser *parser, char *code).

clsParser has a method clsParser::Exec(char *Code). This i've put into the Entry()-function of clsParserThread, like this:

Code: Select all

clsParserThread::ExitCode clsParserThread::Entry() {
    Parser->Exec(Code); 
    return NULL;
}
(...with 'Parser' and 'Code' beeing initialized when creating the clsParserThread-instance).


My questions:

First of all: Instead of calling Parser->Exec(Code);, i now want to use this call: (new clsParserThread(Parser,Code))->Entry(); Is this correct so far, which means, is the ecexution of 'Code' by 'clsParserThread' done parallel to the continued execution of the calling (parent) clsParser?


Will all child-instances of parser be executed parallel, if i start several clsParserThreads in a loop like this:

Code: Select all

for (int i=0; i < CountChildren(); i++)     (new clsParserThread (ChildParser[i], Code[i]))->Entry();

What happens if i use the stack instead of the heap, like this:

Code: Select all

for (int i=0; i < CountChildren(); i++)     clsParserThread (ChildParser[i], Code[i]).Entry();
Normally i would expect crashes...


Thank you,
Frank

Re: wxThread / newbie

Posted: Thu Feb 13, 2020 10:29 pm
by ONEEYEMAN
Hi,
Why not try it in some small test application? Maybe even wx own thread sample...

Thank you.

Re: wxThread / newbie

Posted: Thu Feb 13, 2020 11:50 pm
by doublemax
Instead of calling Parser->Exec(Code);, i now want to use this call: (new clsParserThread(Parser,Code))->Entry(); Is this correct so far, which means, is the ecexution of 'Code' by 'clsParserThread' done parallel to the continued execution of the calling (parent) clsParser?
No, no and no.

If you start the thread with pThread->Run(), the Entry() method will be called internally from inside the new thread context. You're not supposed to call Entry() yourself.

If you want to change your current code structure as little as possible, you should look into OpenMP which is supported by most modern compilers now.

Re: wxThread / newbie

Posted: Thu Feb 13, 2020 11:55 pm
by art-ganseforth
In fact, i used the wxThread example just to understand the basic principal, because is is the first time i try around with wxThread. I used code that i dicribed in my application, and my application compiles and runs as before, but unfortunatly i see no difference at all.

For explanation:
Most CPU-usage is needed by one script, that is executed periodical, called by a timer. This one cuses the ececution of several subitems in a loop.Tehese are independent and can be executed parallel. The CPU-usage of my application depends on the timer-interval. With a timer-interval of max. 60Hz one CPU-core is used at 100%. At this point some thing in my application slow down. Setting the timer-interval up to 150Hz, things get very slow.

Now, after i implemented this wxThread-class, i expected that the CPU-usage distributes over then one cores, but this is not the case. One core is still used at 100% and the others are not used. So i wonder why?

Finally: My code seems so simple to me, that i wonder if i don't do something basically wrong...


Kind regards,
Frank

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 12:02 am
by doublemax
ow, after i implemented this wxThread-class, i expected that the CPU-usage distributes over then one cores, but this is not the case. One core is still used at 100% and the others are not used. So i wonder why?
Hard to tell. Too little and too generic information.

How many worker threads do you have and how do you distribute the work among them?

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 12:19 am
by art-ganseforth
doublemax wrote:
Thu Feb 13, 2020 11:50 pm
Instead of calling Parser->Exec(Code);, i now want to use this call: (new clsParserThread(Parser,Code))->Entry(); Is this correct so far, which means, is the ecexution of 'Code' by 'clsParserThread' done parallel to the continued execution of the calling (parent) clsParser?
No, no and no.

If you start the thread with pThread->Run(), the Entry() method will be called internally from inside the new thread context. You're not supposed to call Entry() yourself.

If you want to change your current code structure as little as possible, you should look into OpenMP which is supported by most modern compilers now.
OpenMP... Hmmm....

I tried, but at first, these basic #pragma omp parallel for etc. do not except 'break' and 'return'-statements etc..So, trying this, only a few loops small loops accepted parallel-statements. However: this i would have figured out if i would be able to link my program with the omp-library. Unfortunatly omp.h is not present in my current gcc (8.0?.2) and also the library seems to be missing.
As you (Doublemaxx) probably know, i've not much experience in soluting problems like this. Anyway i tried, but (again) withot success.

Over this, i'm not sure what OpenMP really does, like eg. does...

Code: Select all

 
 #pragma omp parallel for
 for(int i=0; i< max; i++) AnyFunction();
 
...will lead to parallel execution of the called functions??


However (step by step), why the answer to my first question is 'No'? And why my program works anyway? Is it only the Run()-call?



Thank you,
Frank

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 12:25 am
by doublemax
However (step by step), why the answer to my first question is 'No'?

Code: Select all

(new clsParserThread(Parser,Code))->Entry()
This will just create the thread object and then call the Entry method in the context of the main thread. Nothing else. Which would explain why your program still works, but without using multiple CPUs.

A "clean" version for your problem would be to have a pool of worker threads, and a wxMessageQueue to distribute jobs among them.

As for OpenMP, it's probably not the best tool for this particular problem. But it's still worth looking into.

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 12:36 am
by art-ganseforth
doublemax wrote:
Fri Feb 14, 2020 12:02 am
ow, after i implemented this wxThread-class, i expected that the CPU-usage distributes over then one cores, but this is not the case. One core is still used at 100% and the others are not used. So i wonder why?
Hard to tell. Too little and too generic information.

How many worker threads do you have and how do you distribute the work among them?
Okay... "Workerthreads" - puh! Obviously i was right, that my code seemd to simple...

I don't even know, what a workerthrad is. What i have tested with the exThread-example is:
I reduced it, as much as i could and removed most of the menu-calls (eg. like the GUI-thread), and the classes. The only left classes are 'MyFrame' and 'MyThread'.
The other thing was, to check, if i can access global variables from everywhere.

What is a workerthread?


Thank you,
Frank

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 12:37 am
by doublemax
What is a workerthread?
A "worker thread" is just a generic name for any additional (non-main) thread that does some "work". Another term you might see for this is "secondary thread". Nothing special.

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 12:57 am
by art-ganseforth
doublemax wrote:
Fri Feb 14, 2020 12:25 am
A "clean" version for your problem would be to have a pool of worker threads, and a wxMessageQueue to distribute jobs among them.
I mean this: i've several wxWindows with different content, that should be updated. Some of them need to process a lot of (script-)funtions to update, others are very simple. This updating i would call a 'job' to be done and as all of this updating is independendent, it can be done parallel.

I hoped, that i can simply run one thread per wxWindow, that does the updating. Is there any way to do it jike this?


Kind regards,
Frank

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 1:01 am
by art-ganseforth
doublemax wrote:
Fri Feb 14, 2020 12:37 am
What is a workerthread?
A "worker thread" is just a generic name for any additional (non-main) thread that does some "work". Another term you might see for this is "secondary thread". Nothing special.
Okay, 'workerthreds' = 'threds' except of the main-thread... Their number is not determined. It is some kind of MDI-application with subwindows that can be created and deleted at runtime. Like this, the number of threads depend on the active subwindows.

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 1:03 am
by doublemax
I hoped, that i can simply run one thread per wxWindow, that does the updating. Is there any way to do it jike this?
Theoretically, yes. But converting an application to use multiple CPUs is not a simple switch. You need to know your code and decide how and where is the best place to use threads. It's impossible to give a universal guide for this.

But if your main "consumer" of CPU power is that one piece of code that takes a Parser and Code and returns some result, that's where you should start.

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 1:22 am
by art-ganseforth
doublemax wrote:
Fri Feb 14, 2020 12:25 am
However (step by step), why the answer to my first question is 'No'?

Code: Select all

(new clsParserThread(Parser,Code))->Entry()
This will just create the thread object and then call the Entry method in the context of the main thread. Nothing else. Which would explain why your program still works, but without using multiple CPUs.
I tried

Code: Select all

(new clsParserThread(Parser,Code))->Run();
in between. That crashes :lol:

But anyway: This wxThred-example is quiet short - especially after i've removed half of it. So i think, i should be able, to undesrand the principal...

I think, i will try around a bit more with it...

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 1:33 am
by doublemax

Code: Select all

new clsParserThread(Parser,Code))->Run();
in between. That crashes
The Create() is missing (unless you put that into the thread ctor). The whole creation and starting of a thread is a 3-step process.

Code: Select all

clsParserThread *thread = new clsParserThread(Parser,Code);
if( thread->Create() == wxTHREAD_NO_ERROR )
  thread->Run();

Re: wxThread / newbie

Posted: Fri Feb 14, 2020 2:13 am
by art-ganseforth
doublemax wrote:
Fri Feb 14, 2020 1:03 am
But if your main "consumer" of CPU power is that one piece of code that takes a Parser and Code and returns some result, that's where you should start.
This is my plan, but it is not so simple.

The wxTimer-event calls only one 'entrypoint'. After this, everything is scripted - with several subcalls. There is only one obvious point, where i can simply split the execution into threads. After starting the (main-)script-execution at the entrypoint, there is somewere a call, that starts several subscripts. Currently they are executed sequential, but they can be done parallel because they tont influence each other.

This structure seems to be simelar to the multithreading-structure (one main-script calling several independent sub-scripts to be started at one 'entry-point'). The question is, how to implement it...