wxThread / newbie Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

wxThread / newbie

Post by art-ganseforth » Thu Feb 13, 2020 10:12 pm

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

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4167
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: wxThread / newbie

Post by ONEEYEMAN » Thu Feb 13, 2020 10:29 pm

Hi,
Why not try it in some small test application? Maybe even wx own thread sample...

Thank you.

User avatar
doublemax
Moderator
Moderator
Posts: 14887
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxThread / newbie

Post by doublemax » 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.
Use the source, Luke!

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Thu Feb 13, 2020 11:55 pm

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

User avatar
doublemax
Moderator
Moderator
Posts: 14887
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxThread / newbie

Post by doublemax » 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?
Use the source, Luke!

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Fri Feb 14, 2020 12:19 am

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

User avatar
doublemax
Moderator
Moderator
Posts: 14887
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxThread / newbie

Post by doublemax » 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.

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.
Use the source, Luke!

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Fri Feb 14, 2020 12:36 am

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

User avatar
doublemax
Moderator
Moderator
Posts: 14887
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxThread / newbie

Post by doublemax » 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.
Use the source, Luke!

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Fri Feb 14, 2020 12:57 am

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

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Fri Feb 14, 2020 1:01 am

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.

User avatar
doublemax
Moderator
Moderator
Posts: 14887
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxThread / newbie

Post by doublemax » Fri Feb 14, 2020 1:03 am

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.
Use the source, Luke!

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Fri Feb 14, 2020 1:22 am

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...

User avatar
doublemax
Moderator
Moderator
Posts: 14887
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxThread / newbie

Post by doublemax » Fri Feb 14, 2020 1:33 am

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();
Use the source, Luke!

art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxThread / newbie

Post by art-ganseforth » Fri Feb 14, 2020 2:13 am

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...

Post Reply