Author Topic: Multithreading in QB64?  (Read 3207 times)

0 Members and 1 Guest are viewing this topic.

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Multithreading in QB64?
« on: August 16, 2019, 04:07:06 am »
Hi,
      just one question for experts: is there any multithreding support in QB64 (like functions THREADCREATE in Freebasic) or at least some plans for this in future versions? Thanks.

D.


Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Multithreading in QB64?
« Reply #1 on: August 16, 2019, 04:47:52 am »
Hello. I don't know if you can call it that, but basically it is. With the FREETIMER and on TIMER functions, called subroutines are run (regardless of where the main process is) during the main activity. This method of programming must take this into account, as otherwise there may be seemingly illogical errors.

With this programming method, you can stop and restart individual thread timers via TIMER ON or TIMER OFF. It is very important to watch out for the current screen (when working with virtual screens) because if you do not turn off the timer, the program will leave the current loop and start another thread when the set time is reached. Therefore, there is the option to turn the timer on or off.

Here's a primitive demonstration. The limit is there because otherwise the program run is so fast that you will not notice the timer thread activity.


Code: QB64: [Select]
  1. Thread0 = _FREETIMER
  2. Thread1 = _FREETIMER
  3. Thread2 = _FREETIMER
  4. Thread3 = _FREETIMER
  5.  
  6. ON TIMER(Thread0, .3) Thread_0 'work in this thread every 0.3 seconds
  7. ON TIMER(Thread1, .4) Thread_1 'work in this thread every 0.4 seconds
  8. ON TIMER(Thread2, .5) Thread_2 'work in this thread every 0.5 seconds
  9. ON TIMER(Thread3, .6) Thread_3 'work in this thread every 0.6 seconds
  10.  
  11. TIMER(Thread0) ON
  12. TIMER(Thread1) ON
  13. TIMER(Thread2) ON
  14. TIMER(Thread3) ON
  15.  
  16.     PRINT "My loop run!"
  17.     _LIMIT 10
  18.  
  19.  
  20.  
  21.  
  22.  
  23. SUB Thread_0
  24.     PRINT "Thread 0 run!"
  25.  
  26. SUB Thread_1
  27.     PRINT "Thread 1 run!"
  28.  
  29. SUB Thread_2
  30.     PRINT "Thread 2 run!"
  31.  
  32. SUB Thread_3
  33.     PRINT "Thread 3 run!"
  34.  

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Re: Multithreading in QB64?
« Reply #2 on: August 17, 2019, 06:11:35 pm »
Thanks, Petr, that is realy interesting concept. However, the important thing for me is, if those 4 subs (Therad0-Thread3) would really run on 4 CPU threads simultaneously.
Did you try something like this with some more complex subs while monitoring CPU usage in Task manager?

Actually, I'd like to be able to utilize all the 16 threads of my CPU to preform calculations for many concurent NN agents, which could be too much for just one core to run in realtime. Since I plan each NN agent to act independently (connected just via reading and modyfing shared global variables), it is optimal to divide them into stacks run by 16 paralel threads.

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Re: Multithreading in QB64?
« Reply #3 on: August 17, 2019, 06:46:56 pm »
This modified version of your code seems to run only in one CPU thread, it never leaves the loop in sub Thread_3. But maybe I just did not get the concept right.

Code: QB64: [Select]
  1. quit = 0
  2.  
  3. Thread0 = _FREETIMER
  4. Thread1 = _FREETIMER
  5. Thread2 = _FREETIMER
  6. Thread3 = _FREETIMER
  7.  
  8. ON TIMER(Thread0, .3) Thread_0 'work in this thread every 0.3 seconds
  9. ON TIMER(Thread1, .4) Thread_1 'work in this thread every 0.4 seconds
  10. ON TIMER(Thread2, .5) Thread_2 'work in this thread every 0.5 seconds
  11. ON TIMER(Thread3, .6) Thread_3 'work in this thread every 0.6 seconds
  12.  
  13. TIMER(Thread0) ON
  14. TIMER(Thread1) ON
  15. TIMER(Thread2) ON
  16. TIMER(Thread3) ON
  17.  
  18.     PRINT "My loop run!"
  19. quit = 1
  20.  
  21. SUB Thread_0
  22.     DO
  23.         PRINT "Thread 0 run!"
  24.     LOOP WHILE quit = 0
  25.  
  26. SUB Thread_1
  27.     DO
  28.         PRINT "Thread 1 run!"
  29.     LOOP WHILE quit = 0
  30.  
  31. SUB Thread_2
  32.     DO
  33.         PRINT "Thread 2 run!"
  34.     LOOP WHILE quit = 0
  35.  
  36. SUB Thread_3
  37.     DO
  38.         PRINT "Thread 3 run!"
  39.     LOOP WHILE quit = 0
  40.  


Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Multithreading in QB64?
« Reply #4 on: August 18, 2019, 05:19:08 am »
Running on one thread? Well, that's a shame. So here I would also ask the developers to propose a solution to your request, I assume that some of them have already dealt with it and has an idea how to really use all the threads.

Then, there is my proposal number 2, but that is insane. When using COMMON SHARED, you can share variables from one EXE file to another. Assuming that the system processor kernel load is determined by the operating system, theoretically this could be accomplished by running 14 copies of one program that would share the necessary variables between its copies. (assuming you leave the 2 cores available to the operating system). I tested this procedure under Windows 7. I ran a 5-times compiled EXE file on a 6-core processor. According to the Task Manager, I have achieved a processor load of around 80 percent. By running another EXE file, the computer was already breathing enough. So maybe this will be a better way. I assume that if you write the program using _CONSOLE (if you don't need graphical things), you will reduce a lot of processor cycles and increase processing speed.
I apologize for not having thoroughly tested the previous proposal.

Offline dajan

  • Newbie
  • Posts: 41
    • View Profile
Re: Multithreading in QB64?
« Reply #5 on: August 18, 2019, 03:44:27 pm »
The program I want to multithread uses graphics, it is a game and those AI agents would be individual players, quite a lot of them.
And yeah, runnning multiple copies of exe file, that would be pretty extreme kind of multithreading, but this came to my mind too: first thread (host exe) uses commands SHELL to run multiple instances of itself (client exe). Then individual client instances synchronize shared variables with host instance using PUT and GET through TCP/localhost.
But I don't like such approach very much, it lacks elegance, variables synchronisation is cumbersome and potentialy slow. Maybe it would be more effective to rewrite program to Freebasic, its syntax is quite similar, based on QBasic as well.