The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Airam on August 09, 2009, 11:23:23 PM

Title: Fpu is very slow....
Post by: Airam on August 09, 2009, 11:23:23 PM
Hello!!
I've got a problem with the FPU and the CPU. I have a code similar like that:

procedure proc
  invoke DoSthgWithTheFPU
  invoke FillAListViewWithTheResusltsObtainedBefore
  ret
procedure endp

So when i invoke the DoSthgWithTheFPU procedure I do several calculations with the FPU and I fill some arrays with real10 numbers. Then I invoke FillAListViewWithTheResusltsObtainedBefore procedure where i read the values of the arrays calculated before and convert them to decimal numbers. Once converted the values i add them to a ListView control (in the second procedure).

If i give time between the procedures, for example using a msgbox:
procedure proc
  invoke DoSthgWithTheFPU
  Invoke MessageBox, NULL, Addr text, 0, MB_OK Or MB_ICONERROR
  invoke FillAListViewWithTheResusltsObtainedBefore
  ret
procedure endp

Everything goes perfect, but If i omit the massagebox sentence, i can't see anything at the List View.
How do I give some time between the two procedures?

Thanks in advance.
Title: Re: Fpu is very slow....
Post by: jj2007 on August 09, 2009, 11:27:32 PM
Tried to replace the MessageBox with invoke Sleep, 100?
Title: Re: Fpu is very slow....
Post by: dedndave on August 09, 2009, 11:39:39 PM
you might even try invoke Sleep,0
Title: Re: Fpu is very slow....
Post by: JayPee on August 09, 2009, 11:47:55 PM
Try using the fwait instruction to prevent the cpu from processing further instructions while the fpu is processing
Title: Re: Fpu is very slow....
Post by: dedndave on August 10, 2009, 12:11:57 AM
yah - what JayPee said - lol
Title: Re: Fpu is very slow....
Post by: Airam on August 10, 2009, 08:11:23 AM
Thanks everybody for answering me.
invoke sleep, 100 doesn't work. It seems it waits but the list view isn't filled.
I have put lots of fwaits throughtout the fpu instructions but it still doesn't work.
By the way, the two invokes are called when i select an item on the menu.

Title: Re: Fpu is very slow....
Post by: jj2007 on August 10, 2009, 11:51:04 AM
Quote from: Airam on August 10, 2009, 08:11:23 AM
Thanks everybody for answering me.
invoke sleep, 100 doesn't work. It seems it waits but the list view isn't filled.
I have put lots of fwaits throughtout the fpu instructions but it still doesn't work.
By the way, the two invokes are called when i select an item on the menu.


Raymond says MessageBox is one of the API's that destroy FPU content. Interesting that in your case it helps... ::)
Try to strip down your code to the essential bits, and then post the complete source.
Title: Re: Fpu is very slow....
Post by: dedndave on August 10, 2009, 12:14:30 PM
QuoteRaymond says MessageBox is one of the API's that destroy FPU content. Interesting that in your case it helps...
coincidence, eh ? - Ray was just saying that the other day
it may be because of the fwait thing
that makes me consider - sometimes, it may be a good idea to put fwait at the end of a proc
Title: Re: Fpu is very slow....
Post by: Airam on August 10, 2009, 02:14:11 PM
Hi again!

May be it is related to the fpu stack because I have tested it by sending a message to the status bar instead of displaying a msgbox and it works.
The code is something like this:
procedure proc
  invoke DoSthgWithTheFPU
  Invoke SendMessage, hStatus, SB_SETTEXT, 0, Addr ConvO
  invoke FillAListViewWithTheResusltsObtainedBefore
  ret
procedure endp

This is also another API (the StatusBar, I suppose). I don't think it's a problem of fwait, because i actually have a lot. I also think that is a problem of time, i mean: if i calculate all array values when the program start and then i push a button, it is invoked the second procedure and it is showed the result in the ListView.

P.D: If you want my source code I can send it to your e-mail. I can't post it here because it's a university task.
Title: Re: Fpu is very slow....
Post by: Astro on August 10, 2009, 06:05:56 PM
QuoteI can't post it here because it's a university task.
Ahh - homework...

Quote9. The NO HOMEWORK Rule.
The forum is a technical help forum for assembler language programmers, it will not be used as a location for grovelling to get someone to do your homework. Members who are learning assembler programming at school or similar are welcome but they must do their own work. In this context they will receive assistance if they need it but any dumping of problems in the forum will be removed. Also note that 16 bit DOS code will be moved to the 16 bit DOS forum as this forum is primarily a 32 bit Windows assembler forum.

Where I can, I would be happy to try and explain why you're seeing what you are seeing in terms of behavior, but after having been stung a few months ago in another forum over a task that turned out to be homework that I spent quite some time sorting out to explain (and in the process, solving the very point of the homework), I'm not very inclined to help at all. Nothing personal.

Is the point of this work to figure out why it is doing this? Maybe a homework in program flow/design or something?

If you can be totally open about the purpose of the exercise, I'll take a look.

Best regards,
Astro.
Title: Re: Fpu is very slow....
Post by: Airam on August 10, 2009, 07:55:18 PM
Of course, I understand the rule, Astro. It's logical not to do the homework of other people. But I'm not asking anybody to do my homework, I'm just asking a very specific question about something that doesn't seem very logical to me. I just want an explanation of what happens here. I mean, why does my code works when I use an invoke to an api and if I omit it, why it does not work.

The task that i have to do is just to calcule a thousand values of J0(B) Bessel Function.
But in order to learn more about assembler i decided to create also a Win32 application with a listview, dialogs, ...., and also paint the function. This is not part of the task, but I'm having fun doing that.
In short, I'm doing an unofficial thing :wink

Title: Re: Fpu is very slow....
Post by: Astro on August 10, 2009, 10:29:11 PM
No probs! Sorry if I seemed hostile.

I think you can attach files to PMs, so send me a PM with your code and I'll take a look.

I'm intrigued as to why 'invoke' vs. 'call' has different effects.

If you don't have one, get a debugger. http://en.wikipedia.org/wiki/Ollydbg is excellent.

Best regards,
Astro.
Title: Re: Fpu is very slow....
Post by: MichaelW on August 11, 2009, 01:05:36 AM
Airam,

Are you sure that your FPU code is not generating exceptions? This can have a very large effect on the execution time. In the initialized state the FPU handles exceptions internally, but you can change this behavior with something like this:


;-----------------------------------------
; Bit values for the FPU interrupt masks.
;-----------------------------------------

PM equ 32   ; precision mask       
UM equ 16   ; underflow mask
OM equ 8    ; overflow mask
ZM equ 4    ; zero-divide mask
DM equ 2    ; denormalized operand mask
IM equ 1    ; invalid operation mask

;--------------------------------------------------------
; This macro selectively clears the FPU interrupt masks.
; Example usage: clearintmasks IM or ZM or OM
;--------------------------------------------------------

clearintmasks MACRO maskbits
    push eax
    fstcw [esp]   
    fwait
    pop eax
    and ax, NOT (maskbits) ; parentheses required for proper operation
    push eax
    fldcw [esp]
    pop eax
ENDM

Title: Re: Fpu is very slow....
Post by: dedndave on August 11, 2009, 01:23:36 AM
i bumped into that one the other day, Michael - lol
i was missing a ffree, so the fpu stack got full - slows things WAY down
Title: Re: Fpu is very slow....
Post by: raymond on August 11, 2009, 02:11:02 AM
This does sound VERY weird.

"invoke" is a call instruction and the next instruction should not be performed until the return from the call which would set the EIP to it. An intermediate call to some API should not have any effect on whatever is stored in memory by the first call, on which basis the call to display data in the list box should rely.

I would also volunteer to have a look at your code if you don't mind.

BTW, masking the exception bits in the Control Word means that you have to include some code to take care yourself of such exceptions.  That could be even slower than letting the system taking care of them. Unless you strongly disagree with how the system handles them, it's not worth the effort. You're better off checking the exception flags in the Status Word whenever you would suspect the possibility of some exception and take action at that time (such as aborting further computations, displaying a message box, etc.).
Title: Re: Fpu is very slow....
Post by: dedndave on August 11, 2009, 02:20:14 AM
i have wondered about that (i.e. returns and out-of-order execution)
that means that a return from a subroutine is a serializing instruction ?
MichaelW was saying that cpuid, iret, and bound (i think it was bound) were the only serializing instructions
i tried using iret to serialize rdtsc, but it was slower than cpuid
a regular ret should be much faster, if it will work
now, i trust Michael - he has done a lot of research on this subject
but, his source of information could be wrong
it would make sense that ret serializes instructions
Title: Re: Fpu is very slow....
Post by: Airam on August 11, 2009, 04:58:30 PM
I have send to all of you a private message.

Thank you!!
Title: Re: Fpu is very slow....
Post by: Airam on August 11, 2009, 05:47:25 PM
I forgot to tell you how to use it when you run it.
Go to: Función -> Insertar Función -> Calcular
And then comment/uncomment the invoke SendMessage line of wndMDIMain.
Title: Re: Fpu is very slow....
Post by: Astro on August 11, 2009, 06:13:15 PM
Where can I find these functions?

EDIT: Found them

Best regards,
Astro.
Title: Re: Fpu is very slow....
Post by: Astro on August 11, 2009, 06:15:23 PM
My gut is telling me "race condition" but I can't see where to start finding the source.

You haven't made a typo somewhere have you? Put a ret or a call in the middle of a function or something bizarre like that?

Worse, you don't circular reference your own function do you?

Best regards,
Astro.
Title: Re: Fpu is very slow....
Post by: MichaelW on August 11, 2009, 09:21:31 PM
Airam,

I got your PM and your code. I'm not set up to do much with it, but I did patch together an executable with the essential components, cleared the interrupt masks, and used Dr. Watson to catch the exceptions.

I started with:

clearintmasks UM or OM or ZM or IM

Leaving out DM and PM on the assumption that these are less serious than the others are. The first exception was EXCEPTION_FLT_DIVIDE_BY_ZERO in this code (fault detected at last instruction, but the problem is obviously the FDIVR instruction):

Fld Real10 Ptr [Edi]  ; x | -
Fld St(0)             ; x | x | -
Fld EIGHT             ; 8.0 | x | x | -
Fdivr                 ; 8.0 / x | x | -
Fld St(0)             ; 8.0 / x | 8.0 / x | x | -


I then eliminated ZM from the mask, and the next exception was EXCEPTION_FLT_INVALID_OPERATION in this code (fault detected at the last instruction, so the problem is probably the FSUBR instruction):

Fmul St(0), St(3) ; cos(xx) · ans1 | sin(xx) · ans2 · z | ans2 | ans1 | z | x | -
Fwait
Fsubr             ; cos(xx) · ans1 - sin(xx) · ans2 · z | ans2 | ans1 | z | x | -
Fstp St(1)        ; cos(xx) · ans1 - sin(xx) · ans2 · z | ans1 | z | x | -


Judging from the complexity of the code I suspect that other exceptions are being generated, and possibly many others. And judging from the size of your arrays, if even most of the elements are being used, this would explain the slow execution.