BBC BASIC
« Parallel Assembly »

Welcome Guest. Please Login or Register.
Mar 31st, 2018, 11:09pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
We apologize Conforums does not have any export functions to migrate data.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

Thank you Conforums members.
Cross-platform BBC BASIC (Windows, Linux x86, Mac OS-X, Android, iOS, Raspberry Pi)
BBC BASIC Resources
BBC BASIC Help Documentation
BBC BASIC for Windows Home Page
BBC BASIC Programmers' Reference
BBC BASIC Beginners' Tutorial
BBC BASIC for SDL 2.0 Home Page
BBC BASIC Discussion Group

« Previous Topic | Next Topic »
Pages: 1 2  Notify Send Topic Print
 hotthread  Author  Topic: Parallel Assembly  (Read 1237 times)
Ric
New Member
Image


member is offline

Avatar




PM


Posts: 30
xx Re: Parallel Assembly
« Reply #6 on: Apr 18th, 2017, 07:49am »

Unlike you I am not a programming guru, I know what I want to achieve but don't necessarily know how to go about it. I will ask in a different way.

I would like to have two routines doing calculations running in the background and another that is capable of asking them for answers by passing and receiving parameters. All three programs/routines would run at the same time. Is this possible?

I do not know whether threads are needed, you suggested them. Simple would be a call with 1 or no parameters, create thread appears to have 8 of which I know not any of them are for or how to calculate.

Can what I am asking be done?

Ric
User IP Logged

You can't succeed without failing a few times first, CHIN UP.
Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 803
xx Re: Parallel Assembly
« Reply #7 on: Apr 18th, 2017, 08:40am »

on Apr 18th, 2017, 07:49am, Ric wrote:
I would like to have two routines doing calculations running in the background and another that is capable of asking them for answers by passing and receiving parameters. All three programs/routines would run at the same time. Is this possible?

This sounds very similar to your original question, except that you don't mention assembly language. It makes a big difference whether you want to do the "background" calculations in BASIC or in assembly language!

In the case of BASIC code the only practical way of performing your background tasks would be by running multiple copies of BBC BASIC. This will work, but because they run in different processes arranging the necessary communication and synchronisation between the tasks, so that they cooperate to achieve the wanted end result, may not be trivial.

If you are happy to perform the "background" calculations in assembler (i.e. machine) code then, as I said, threads will achieve that. However, as I tried to explain before, there is a subtle difference between running "at the same time" (which is your phrase) and running 'concurrently'.

Because of the (typically) many things that are happening on a PC that you are not directly aware of - just look in Task Manager to get an idea - you can never guarantee that there will be sufficient spare CPU cores to run your multiple tasks literally simultaneously, so you should not make that a requirement.

Rather, by running the tasks as different threads it is then up to the Windows kernel to schedule them on different cores if it can but to use time-sharing on fewer cores if it can't. Is it this factor that is causing you to doubt whether threads are suitable? I can assure you that it is perfectly normal to allow the OS this flexibility, rather than to attempt to force certain pieces of code to run on certain cores.

So if I assume that using assembler code is acceptable, and that you can relax your requirement that the tasks run literally "at the same time", then my opinion is not changed that threads are what you want. If you are already familiar with running assembler code using CALL or USR then, as I said, it is a simple change to using SYS "CreateThread" instead.

For the precise syntax of the CreateThread API you can either refer to its formal description at MSDN or simply copy-and-paste the relevant statement from either WINLIB2 or WINLIB4 (or look at both to see, and hopefully understand, how they relate). For example the statement in WINLIB2 is:

Code:
      SYS "CreateThread", 0, 1024, start%, 0, 0, ^I% TO H% 

I cannot literally list here the code you will need (even if that was desirable) because only you know things like how, and under what circumstances, the thread(s) will be terminated, how information will be passed into and out of the threads, how the threads will be synchronised and coordinated etc.

I suggest that you try it; you have all the information you need. Write the multiple tasks as assembler code, and test them independently using CALL (if that is practical). Once you are confident the code is working as you intend, change the CALL statements to SYS "CreateThread" statements (copied from one of the libraries if you must) and then see if everything it working as it should.

I have been careful to write this reply using straightforward English, using short sentences and short paragraphs, and using no technical jargon other than what is unavoidable given the subject matter.

Richard.
« Last Edit: Apr 18th, 2017, 08:59am by Richard Russell » User IP Logged

Ric
New Member
Image


member is offline

Avatar




PM


Posts: 30
xx Re: Parallel Assembly
« Reply #8 on: Apr 18th, 2017, 09:42am »

Thanks Richard,

It is questions like "what are ^I% and H%" and what do they need to be set to.
I assume start% is the start address of the assembly to be created as a thread?
Can I simply exchange start% for the address label?

They may be simple questions, but without answers I am flummoxed.

Regards Ric
User IP Logged

You can't succeed without failing a few times first, CHIN UP.
Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 803
xx Re: Parallel Assembly
« Reply #9 on: Apr 18th, 2017, 1:21pm »

on Apr 18th, 2017, 09:42am, Ric wrote:
It is questions like "what are ^I% and H%" and what do they need to be set to.

It's all explained in great detail at the MSDN page to which I linked (or in the case of BBCSDL at the SDL Wiki). You cannot expect to call Windows API functions without referring to their descriptions at MSDN. It would be wasteful duplication (and probably a violation of Copyright) for me to reproduce here what is written there, and valuable links to other MSDN references might be lost.

Quote:
They may be simple questions, but without answers I am flummoxed.

Every programming language that provides support for calling Windows API functions (and functions in other DLLs), whether it be by BBC BASIC's SYS statement, or Liberty BASIC's CALLDLL statement, or Visual BASIC's __stdcall declaration, requires the programmer to consult MSDN (etc.) to discover how the function is called, what its parameters are and what value (if any) it returns.

Richard.
User IP Logged

Ric
New Member
Image


member is offline

Avatar




PM


Posts: 30
xx Re: Parallel Assembly
« Reply #10 on: Apr 19th, 2017, 4:18pm »

I have now managed to create threads successfully, using help from MSDN(etc...) and a post by Michael Hutton. So many thanks, now I can see clearly, you were right, it is simple😊 There is just one thing I can not figure, why is the last parameter X TO y and not just an address/variable?

Regards Ric
User IP Logged

You can't succeed without failing a few times first, CHIN UP.
Ric
New Member
Image


member is offline

Avatar




PM


Posts: 30
xx Re: Parallel Assembly
« Reply #11 on: Apr 28th, 2017, 8:00pm »

Richard

It has taken a while but I now understand that it is not x to y after the last comma, but the first six parameters to thread handle. I have created both BASIC and ASM versions of "CreateThread" and in BASIC my laptop will allow 5 threads, but appears to only run two at a time (is this normal?), but in ASM when I try to create more than one thread the program crashes, is this because I can only create two threads at the same time and the current ASM code counts as one of them? Or am I missing something?

The code to create the codes in ASM is
Code:
        push              0        push              0        push              0        push              start        push              1024        push              0        CALL              "CreateThread"        mov               [thread1],             eax 


Regards Ric
User IP Logged

You can't succeed without failing a few times first, CHIN UP.
Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 803
xx Re: Parallel Assembly
« Reply #12 on: Apr 28th, 2017, 9:21pm »

on Apr 28th, 2017, 8:00pm, Ric wrote:
when I try to create more than one thread the program crashes, is this because I can only create two threads at the same time and the current ASM code counts as one of them?

You ought to be able to run hundreds of threads (at least!). To get a feel for the number of threads typically running on your PC, start Task Manager, select the 'Details' tab and then right-click on any of the column headings. One of the options you will see is 'Select Columns' - click on that and then tick the 'Threads' checkbox. Now you will see how many threads each process is running - the total is likely to be several hundred!

So if you are finding that you cannot start more than two threads there must be another reason. You may be able to discover what that is by using the code listed in the BB4W Help manual under 'Accessing the Windows API... Discovering an unknown error' (or you can read it online here). Copy that code into your program and use it to discover the Windows error when your thread creation fails.

Quote:
The code to create the codes in ASM is

Creating a thread using assembler code is unusual and probably makes it rather more difficult to debug. Do you need to? Couldn't you create all the threads you need initially, using BASIC code? There's a considerable overhead in creating a thread so it's more efficient to create it just once, at the start, rather than to repetitively terminate the thread and then create another one.

Richard.
User IP Logged

svein
New Member
Image


member is offline

Avatar




PM


Posts: 15
xx Re: Parallel Assembly
« Reply #13 on: Jun 22nd, 2017, 6:12pm »

Ric:

This might get you started, don't know who wrote it.
Disregard the middle bit (system info).

Code:
      REM!WC      MAXIMUM_PROCESSORS = 32      CREATE_SUSPENDED = &4      INFINITE = &FFFFFFFF      _TRUE = 1      A% = 1      B% = 1      :\      \\ assemble two different (pointless) routines to increment A% and B%      \      DIM code 50, L%-1      FOR pass=8 TO 10 STEP 2        P% = code        [        OPT pass          .ThreadProc1        inc dword [^A%]        cmp dword [^A%],0        jne ThreadProc1        ret          .ThreadProc2        inc dword [^B%]        cmp dword [^B%],0        jne ThreadProc2        ret          ]      NEXT      :\      \\ Declare SYSTEM_INFO structure      \      DIM _SYSTEM_INFO{ wProcessorArchitecture%,      \ Only lower word if valid: high word is wReserved - was dwOemID      \                 dwPageSize%,                  \      \                 lpMinimumApplicationAddress%, \      \                 lpMaximumApplicationAddress%, \      \                 dwActiveProcessorMask%,       \      \                 dwNumberOfProcessors%,        \      \                 dwProcessorType%,             \      \                 dwAllocationGranulatiry%,     \      \                 wProcessorLevel{l&,h&},       \      \                 wProcessorRevision{l&,h&}    }      SYS "GetSystemInfo", _SYSTEM_INFO{}      PRINT "Number of processors available: ";_SYSTEM_INFO.dwNumberOfProcessors%      :\      \\ Create the threads and store their handles in an array      \      DIM hThread%(1)      :\      \\ ON ERROR and ON CLOSE to cleanup thread handles      \      ON ERROR PROCCleanup:REPORT:END      ON CLOSE PROCCleanup:QUIT      :\      \\ Create the threads in a suspended state      \      SYS "CreateThread", 0, 1024, ThreadProc1, 0, CREATE_SUSPENDED, 0 TO hThread%(0)      IF hThread%(0) = 0 THEN ERROR,"Failed to create Thread 1."      SYS "CreateThread", 0, 1024, ThreadProc2, 0, CREATE_SUSPENDED, 0 TO hThread%(1)      IF hThread%(1) = 0 THEN ERROR,"Failed to create Thread 2."      :\      \\ Get the current ideal processor for each thread      \      SYS "SetThreadIdealProcessor", hThread%(0), MAXIMUM_PROCESSORS TO current0%      PRINT "Thread 1 is currently on : ";current0%      SYS "SetThreadIdealProcessor", hThread%(1), MAXIMUM_PROCESSORS TO current1%      PRINT "Thread 2 is currently on : ";current1%      IF current0% = current1% AND _SYSTEM_INFO.dwNumberOfProcessors%>1 THEN        SYS "SetThreadIdealProcessor", hThread%(1), 1 TO R%        IF R%=-1 THEN PRINT"Couldn't change the processor for the 2nd thread."      ENDIF      :\      \\ Wait a bit, check out Task Manager maybe...      \      PRINT "Waiting....."      WAIT 500      PRINT "Starting threads."      PRINT A%,B%      :\      \\ |||Fry||| those processors      \      SYS "ResumeThread", hThread%(0)      SYS "ResumeThread", hThread%(1)      :\      \\ Wait until both threads have stopped and then exit      \      SYS "WaitForMultipleObjects", 2, ^hThread%(0), _TRUE, INFINITE TO R%      PRINT A%,B%      PROCCleanup      END      :\      \\ Close the thread objects      \      DEFPROCCleanup      FOR I%=0 TO 1        IF hThread%(I%) THEN SYS "CloseHandle", hThread%(I%) : hThread%(I%) = 0      NEXT      ENDPROC 


Svein
User IP Logged

Richard Russell
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM


Posts: 803
xx Re: Parallel Assembly
« Reply #14 on: Jun 22nd, 2017, 7:51pm »

on Jun 22nd, 2017, 6:12pm, svein wrote:
This might get you started, don't know who wrote it.

It's important to note this comment:

Code:
      \\ |||Fry||| those processors 

... and it certainly does! I would be very cautious about running this program unless you are confident about the efficiency of your CPU's cooling system!

Another thing to note is that, as it stands, the program cannot be terminated other than by using Task Manager (which will kill the BB4W IDE at the same time); the threads would exit eventually but only after 2^32 loops!

I wonder if the original author thought that closing a thread's handle terminates the thread (there's an ON CLOSE handler that closes both thread handles) but it doesn't. In fact it's perfectly OK to close a thread's handle immediately after it has been started; it won't affect anything unless the handle is needed later.

I would prefer to adapt the program so that the threads are forced to terminate on clicking Close, which can be achieved by changing the last few lines as follows:

Code:
      REM Wait until both threads have stopped and then exit      REPEAT        SYS "WaitForMultipleObjects", 2, ^hThread%(0), _TRUE, 100 TO R%      UNTIL R% <> 258      PRINT A%,B%      PROCCleanup      END      REM Close the thread objects      DEFPROCCleanup      A% = TRUE : B% = TRUE      FOR I%=0 TO 1        IF hThread%(I%) THEN SYS "CloseHandle", hThread%(I%) : hThread%(I%) = 0      NEXT      ENDPROC 

My final suggestion would be to give careful thought to whether 'SetThreadIdealProcessor' or 'SetThreadAffinityMask' is most appropriate for your program.

Richard.
User IP Logged

Ric
New Member
Image


member is offline

Avatar




PM


Posts: 30
xx Re: Parallel Assembly
« Reply #15 on: Jun 23rd, 2017, 5:33pm »

Thanks guys, I have managed to create the style of code I was after which works very similar to the last two posts. I have had to go off on a tangent, but will be back to this at a later date.

Ric
User IP Logged

You can't succeed without failing a few times first, CHIN UP.
Pages: 1 2  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls