BBC BASIC for Windows
General >> General Board >> Instruction speed
http://bb4w.conforums.com/index.cgi?board=general&action=display&num=1453487407

Instruction speed
Post by Ric on Jan 22nd, 2016, 5:30pm

Does anyone know what the difference is between basic and assembler speed? Ie if I used the instruction X+=1 how long would it take compared to [add eax,1]?
Working on 3D graphics and just wondered what the time saving would be.
Re: Instruction speed
Post by DDRM on Jan 28th, 2016, 3:35pm

Hi Ric,

Probably a lot (an order of magnitude?) - but I suspect it wouldn't be worth the overhead of calling an assembler routine for one instruction!

You might find that some things are so fast that it's not worth it - for example, whole-array operations can speed things up dramatically if used cleverly.

The other thing to think about is the relative time spent doing whatever calculations you are doing and the time spent doing the plotting. If you are doing the latter in BB4W graphics commands then it is likely the time spent doing the calculations is negligible - on the other hand, if you are passing all the actual plotting to D3D, for example, it may be worth speeding up your calculations.

David Williams would be a good person to comment on this, since he's done a lot with fancy graphics plotting...

...or you could email Richard Russell, of course - he's a great advocate of the assembler.

Hope that's useful.

D
Re: Instruction speed
Post by ady on Jan 30th, 2016, 01:59am

Assembler is miles faster, especially if integers are being used. Using C for calculations can give you a reasonable "assembler" comparison against basic when things get more complicated

As mentioned though, clever basic programming can save an awful lot of coding time while producing a perfectly reasonable speed of execution
One of my favourites is Richards sudoko solver
Re: Instruction speed
Post by Zaphod on Jan 30th, 2016, 02:45am

Quote:
One of my favourites is Richards sudoko solver


Yes that is a pretty amazing piece of code, clever thinking and great use of recursion. This was unnecessarily obscure though;
Code:
IF P% P% = LOGP%/LOG2+1.5 

since LOG2 is a constant I am sure that using the LOG function for that slows it down just a bit.
Just to show how much you can do in a single line with some thought here are the comments I added to my version once I figured it out...
Code:
        IF P% P% = LOGP%/LOG2+1.5  
REM convert from bit position to number. Uses log theory to convert from a number to the base 2 to a number base 10
REM say P% was %10000 or 2^5 this needs to be converted to 5. Log to the base 2 would give us that.
REM but we have log to base 10 function available. So Log N to base 2 = log N to base 10 / log 2 to base 10
REM The +1.5 is 0.5 to avoid a rounding error as we place the result in to an integer, and 1 to get the right ASCII code below.
 


If the original questioner has not already mastered the Profiler Utility I would recommend that to find out where the program is spending all its time and then adjusting only those parts that are needed. And as Richard often showed rearranging the problem that you are trying to solve sometimes makes it many times as fast.

Z

Re: Instruction speed
Post by Ric on Feb 2nd, 2016, 07:36am

Thanks guys, I am trying to produce realistic 3d graphics for gaming. The theory is quite easy and the number crunching laborious, but it is the graphics speed which is slow. In essence I need to be able to update every screen pixel about 30 times a second, if this can be done in basic I would be happy to talk to anybody that can offer insight. But my initial thoughts are to write assembler routines for this. And the question about speed was to see if it was worth pursuing or knocking it on the head. The latter is not an option really as I have the bit between my teeth and failure is not an option wink grin
Ric
Re: Instruction speed
Post by Ric on Feb 2nd, 2016, 09:11am

Just a little aside, after changing the DIB section using assembler, the screen has to be *REFRESHed to display changes. Is there a way to enable this to be done automatically and/or done from within the assembler routine?
Re: Instruction speed
Post by DDRM on Feb 2nd, 2016, 4:42pm

Hi Ric,

So you are already doing the most important thing: writing directly to a DIBSection rather than using BB4W drawing commands...

To answer your supplementary question, you can replace the *REFRESH with a call to "InvalidateRect" - either in BB4W using the SYS command, or in your assembler using call (see the section on "calling the Windows API" in the Assembler section of the manual).

The other comment I'd make is to ask whether you really need to redraw all the pixels every frame, and if so, whether many of them will be different. For example, if you can keep a "background image" in a separate bitmap and use the Windows Blitting functions to copy it to your working buffer, it will be MUCH faster than changing each point individually - and you could offset it, so that you could have a moving background, if necessary (and if your background image is bigger than the view).

If you actually only need to update part of the screen, using InvalidateRect with specific coordinates will be substantially faster than updating the whole screen each time.

Are you going to treat us to a demo of this project sometime?

cheesy

D
Re: Instruction speed
Post by Ric on Feb 3rd, 2016, 8:35pm

;D ;D ;D

Thanks DDRM.

I can only think of being able to redraw (repixel) every time because the screen will be in 3D depth perception view which will change constantly. Ho Hum!!

The demo is a long way off because there are a lot of aspects of the 3D gaming that I have yet to learn, (until recently it has been 30 years since I programmed a computer), and as I am only able to get max 1/2 to 1 hour a night in, it takes more time than I would wish. ;) But I will post samples of the code as I learn it for anyone who is interested in 3D development. Code:
 


I have run the following program with the "InvalidateRect" command both present and missing.

With the command present the Assembler version refreshes 376 times a second and the Basic version 1.4 times a second.

But if the command is missing the Assembler version refreshes 622 times per second and the Basic version again 1.4 per second.

Inference the Assembler runs approx. 450 times faster than the Basic version, not quite the facto I was expecting!

10 VDU 23,22,1346;674;16,16,16,0
20
30 REM *** DO NOT PRESS ESCAPE TO EXIT ASSEMBLER VERSION ***
40
50 DIM code% NOTEND AND 2047, code% 6143
60
70
80
90 CLS
100 DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, ClrUsed%, ClrImportant%}
110 DIM bmi{Header{} = BITMAPINFOHEADER{}}
120 bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
130 bmi.Header.Width% = 1346
140 bmi.Header.Height% = 674
150 bmi.Header.Planes.l& = 1
160 bmi.Header.BitCount.l& = 32
170
180 SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
190 IF hbitmap%=0 ERROR 100, "Couldn't create DIBSection"
200
210 SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
220 SYS "DeleteObject", oldhbm%
230 SYS "InvalidateRect", @hwnd%, 0, 0
240
250 FOR I% = 0 TO 2 STEP 2
260 P% = code%
270 [
280 OPT I%
290 .start
300 mov eax, &00
310 mov edx, [^bits%]
320 mov ebx, edx
330 add edx, 3628812
340 .loop
350 mov [edx], eax
360 sub edx, 4
370 cmp edx, ebx
380 jne loop
390 add edx, 3628812
400 add eax, 1
410 push eax
420 push ebx
430 push edx
440 push 0
450 push 0
460 push @hwnd%
470 call "InvalidateRect"
480 pop edx
490 pop ebx
500 pop eax
510 cmp eax, &00010000
520 jne loop
530 ret
540
550 ]
560
570 NEXT I%
580
590 INPUT "RUN (B)asic or (A)ssembler ";choice$
600 IF choice$="A" OR choice$="a" THEN 640
610 IF choice$="B" OR choice$="b" THEN 710
620 GOTO 590
630
640 TIME=0
650 CALL start
660 PRINT TIME
670 SYS "InvalidateRect",@hwnd%,0,0
680
690 GOTO 590
700
710 TIME=0
720 A%=0
730 D%=bits%
740 B%=D%
750 D%+=3628812
760 ?D%=A%
770 D%-=4
780 IF D%<>B% THEN 760
790 D%+=3628812
800 A%+=1
810 SYS "InvalidateRect",@hwnd%,0,0
820 IF A%<>256 THEN 760
830 PRINT TIME
840
850 GOTO 590

Re: Instruction speed
Post by Ric on Feb 3rd, 2016, 8:37pm

[code][ 10 VDU 23,22,1346;674;16,16,16,0
20
30 REM *** DO NOT PRESS ESCAPE TO EXIT ASSEMBLER VERSION ***
40
50 DIM code% NOTEND AND 2047, code% 6143
60
70
80
90 CLS
100 DIM BITMAPINFOHEADER{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, ClrUsed%, ClrImportant%}
110 DIM bmi{Header{} = BITMAPINFOHEADER{}}
120 bmi.Header.Size% = DIM(BITMAPINFOHEADER{})
130 bmi.Header.Width% = 1346
140 bmi.Header.Height% = 674
150 bmi.Header.Planes.l& = 1
160 bmi.Header.BitCount.l& = 32
170
180 SYS "CreateDIBSection", @memhdc%, bmi{}, 0, ^bits%, 0, 0 TO hbitmap%
190 IF hbitmap%=0 ERROR 100, "Couldn't create DIBSection"
200
210 SYS "SelectObject", @memhdc%, hbitmap% TO oldhbm%
220 SYS "DeleteObject", oldhbm%
230 SYS "InvalidateRect", @hwnd%, 0, 0
240
250 FOR I% = 0 TO 2 STEP 2
260 P% = code%
270 [
280 OPT I%
290 .start
300 mov eax, &00
310 mov edx, [^bits%]
320 mov ebx, edx
330 add edx, 3628812
340 .loop
350 mov [edx], eax
360 sub edx, 4
370 cmp edx, ebx
380 jne loop
390 add edx, 3628812
400 add eax, 1
410 push eax
420 push ebx
430 push edx
440 push 0
450 push 0
460 push @hwnd%
470 call "InvalidateRect"
480 pop edx
490 pop ebx
500 pop eax
510 cmp eax, &00010000
520 jne loop
530 ret
540
550 ]
560
570 NEXT I%
580
590 INPUT "RUN (B)asic or (A)ssembler ";choice$
600 IF choice$="A" OR choice$="a" THEN 640
610 IF choice$="B" OR choice$="b" THEN 710
620 GOTO 590
630
640 TIME=0
650 CALL start
660 PRINT TIME
670 SYS "InvalidateRect",@hwnd%,0,0
680
690 GOTO 590
700
710 TIME=0
720 A%=0
730 D%=bits%
740 B%=D%
750 D%+=3628812
760 ?D%=A%
770 D%-=4
780 IF D%<>B% THEN 760
790 D%+=3628812
800 A%+=1
810 SYS "InvalidateRect",@hwnd%,0,0
820 IF A%<>256 THEN 760
830 PRINT TIME
840
850 GOTO 590
]
Re: Instruction speed
Post by Ric on Feb 3rd, 2016, 8:38pm

How do you insert code?
Re: Instruction speed
Post by sveinioslo on Feb 8th, 2016, 10:45am

Place code between code tags.
[.code]
PRINT "Test"
[./code]

Remove the dots in [.code][./code]
Code:
PRINT "Test"
 


Svein
Re: Instruction speed
Post by DDRM on Feb 8th, 2016, 12:03pm

Hi Ric,

Thanks for the demo(s) - one of which appears to have disappeared again!

The assembler re-writing is certainly spectacularly fast, even if the display isn't that exciting yet... wink

...maybe I need to revisit my need to get to grips with some simple assembler processing.

The cube demo (which appeared but now seems to have disappeared) is impressive - but if that is the kind of thing you want to do, can I encourage you to think about using Direct 3D via the library? If you look in the samples that came with BB4W (under graphics) you'll find a very simple example called pyramid.bbc,which is not dissimilar to your cube but runs more smoothly. D3D is nice, because you get rotation, scaling etc of the object "for free", and you can also move the viewpoint - very powerful if you are thinking of a game where you move around.

That relies on a pre-defined file for the shape, but it is possible to generate the buffer on the fly - if you look at the proto-flightsim I posted here:

http://bb4w.conforums.com/index.cgi?board=graphics&action=display&num=1439311250

I make a map, generate a D3D vertex buffer on the fly, and render it. There is also some code to control lighting, which you might find useful.

There's been quite a lot of debate here about different D3D models - the one that comes with BB4W uses D3D8, because the support files are freely available, though Richard also produced a D3D9 equivalent, as well as some files to map all the methods for different parts of it (sorry, my nomenclature is all over the place..). Others have argued for D3D11 - but that works rather differently, so would take some getting used to, while D3D9 is pretty like D3D8.

Best wishes,

D
Re: Instruction speed
Post by Ric on Feb 8th, 2016, 9:51pm

DDRM, you are right about the speed. It is very impressive. I will look at D3D, but the challenge I set my self was to produce a 3D game in asm. I am much further on than the demo would suggest, writing small bits of code to perform the tasks required. I will move the chat to 3D gaming project as only a very small percentage of the code is in asm at the moment (that challenge has yet to come!). I am experimenting in Basic first which is why the images are jerky. But one day I will succeed and all the routines will be in asm wink