Code Comments

Programming Forum and web based access to our favorite programming groups.
For Programmers: Free Programming Magazines
Registration is free! Edit your profileCalendarFind other membersFrequently Asked QuestionsSearch -> 
Post New Thread











Thread
Author

Bit intrinsic to extract sign of a real number - possible?
Need to detect when a (real 8) number changes sign.  Seems the most
efficient way should be to test the bit that defines whether the
number is pos or neg?  However, all the BIT funtiions (apart from
TRANSFER) seem to operate only on integers.  Surely there is a way to
extract the bit that sets +/- for a real number.

My current code is along the lines (a = real 8)


DO i = 2,n
if(a(i)*a(i-1) > 0.d0) CYCLE  ! say 90% of cases
... do some minor stuff (one statement)
END DO


That requires a real*real & i-1 operation for every case.

I can use SIGN, but in timinig tests that worked out a lot slower than
the current code.    If they were integer(8) numbers, the test I
envisage would be along the lines:


logical(1) no_change
integer(8) num(:)
integer(4) i, n

ALLOCATE( num( ...) )

no_change = BTEST (num(1), 63)
DO i = 2,n
if( BTEST (num(i), 63) == no_change) CYCLE
no_change = .NOT.no_change
... do some stuff
END DO


Anything equivalent I could use for real numbers?

David




Report this thread to moderator Post Follow-up to this message
Old Post
dud_address@xparadise.net.nz
08-18-04 08:57 AM


Re: Bit intrinsic to extract sign of a real number - possible?
<dud_address@xparadise.net.nz> wrote in message
 news:u9j5i0l40udqrbl0nt5qrcq8lgu1nv2u0m@
4ax.com...

> DO i = 2,n
>     if(a(i)*a(i-1) > 0.d0) CYCLE  ! say 90% of cases
>     .... do some minor stuff (one statement)
> END DO

> That requires a real*real & i-1 operation for every case.

Floating point multiplication is cheap or even free on
modern processors.  Heck, I even wrote some assembly
code once for a 21164 which used the floating point
multiplier to emulate integer addition, and this actually
made the code run faster!  On processors with a fully-
pipelined floating point multiplier like an Alpha or an
Athlon, floating point multiplication is more often than
not free.  I just finished my Fortran convolution code
generator (see my website) and the last thing I worried
about was the cost of floating point multiplications,
although I minimized their number when doing so didn't
cause an increase in the count of floating point additions.
Swizzling floating point numbers through the integer
register file is kind of an old-fashioned trick that
normally leads to slower code on current processors.  In
your case you might be able to get things to go faster by
doing so because this is one of the rare cases where
floating point multiplications outnumber other operations.
This would be easy in assembly, but in Fortran you would
have to either be able to EQUIVALENCE the floating point
array to an integer array or use TRANSFER to move a
bitwise copy of the floating point variable into an integer
variable.  Then, assuming no D_FLOAT or G_FLOAT variables,
you would test the high bit of the integer as before.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end



Report this thread to moderator Post Follow-up to this message
Old Post
James Van Buskirk
08-18-04 08:57 AM


Re: Bit intrinsic to extract sign of a real number - possible?
dud_address@xparadise.net.nz wrote:
> Need to detect when a (real 8) number changes sign.  Seems the most
> efficient way should be to test the bit that defines whether the
> number is pos or neg?  However, all the BIT funtiions (apart from
> TRANSFER) seem to operate only on integers.  Surely there is a way to
> extract the bit that sets +/- for a real number.
>
> My current code is along the lines (a = real 8)
>
>
> DO i = 2,n
>    if(a(i)*a(i-1) > 0.d0) CYCLE  ! say 90% of cases

How about :
if( (a(i)>0.d0) .EQV. (a(i-1)>0.do) ) CYCLE

>    .... do some minor stuff (one statement)
> END DO
>

No bit twiddling required, thus portable. You may or may not improve
on it by saving the result of (a(i)>0.d0) in a logical variable and
use that instead of (a(i-1)>0.do) in the next iteration.

>
> That requires a real*real & i-1 operation for every case.
>

Only a test can tell whether any of this is really faster than a
multiplication on your machine.

--
Klaus Wacker              wacker@Physik.Uni-Dortmund.DE
Experimentelle Physik V   http://www.physik.uni-dortmund.de/~wacker
Universitaet Dortmund     Tel.: +49 231 755 3587
D-44221 Dortmund          Fax:  +49 231 755 4547

Report this thread to moderator Post Follow-up to this message
Old Post
Klaus Wacker
08-18-04 08:58 PM


Re: Bit intrinsic to extract sign of a real number - possible?
On Wed, 18 Aug 2004 06:03:41 GMT, "James Van Buskirk"
<not_valid@comcast.net> wrote:

><dud_address@xparadise.net.nz> wrote in message
> news:u9j5i0l40udqrbl0nt5qrcq8lgu1nv2u0m@
4ax.com...
> 
> 
>
.....

>               ..........       On processors with a fully-
>pipelined floating point multiplier like an Alpha or an
>Athlon, floating point multiplication is more often than
>not free.
.......

>This would be easy in assembly, but in Fortran you would
>have to either be able to EQUIVALENCE the floating point
>array to an integer array or use TRANSFER to move a
>bitwise copy of the floating point variable into an integer
>variable.  Then, assuming no D_FLOAT or G_FLOAT variables,
>you would test the high bit of the integer as before.


James & Klaus - many thanks

I have now conceded defeat!

EQUIVALENCE worked fine, but unfortunately my "a(i)" is actually
"gn(i,k)-yg" where yg varies on different walks through this part of
the code, so I need an extra line "gn8 = gn(i,k)-yg" before the test,
where gn8 is equivalenced to in8.   Resulting code is

gn8 = gn(1,k)-yg
no_change = BTEST (in8, 63)
DO i = 2,n
gn8 = gn(i,k)-yg      ! ### the "killer" ? ###
if( BTEST (in8, 63) == no_change) CYCLE
no_change = .NOT.no_change
... do some stuff
END DO

Because this adds an extra real8 subtraction in every case, it is
about 40% slower than my original version; ie:

if((gn(i,k)-yg)*(gn(i-1,k)-yg) > 0.d0) CYCLE

Similarly for Klaus's suggestion - that was also c. 40% slower.

I revised my code using SIGN to parallel my original BTEST example
(originally I used 2 SIGN's each cycle!). ie revised version:

real(8) is_same
....
is_same = SIGN(1.0, gn(1,k)-yg)
DO i = 2,n
if( SIGN(1.0, gn(i,k)-yg) == is_same) CYCLE
is_same = -is_same
......

Still took 25% longer than my original real*real option.

I never managed to get the TRANSFER option to work - even after I got
my facts straight about the locations of the sign bit in real &
integer values (my other post) !!!   I found a couple of other posts
re abysmal performance of TRANSFER so I see no point in pursuing that
further.

Looks like James' comments about near zero cost of real multiplication
might be close to the mark **
(my tests run on an Athlon / IVF8 system).

############

It did seem though, that without the extra line of code the BTEST
option could potentially be the fastest.

Seems a pity that there is not an equivalent Bit operator for reals,
even if restricted solely to testing the sign bit.    Perhaps BTEST
could be extended to testing the sign bit of a real variable.

Bit testing for +/- of a real seems a worthwhile exception that should
be easy (?) to implement.   Or perhaps "in source" assembly code
should be permitted?

The performance of SIGN is fairly disappointing (at least in IVF8).

David

############

** I actually tried about 3 variations of the real*real code & they
consistently resulted in the same CPU time, despite apparent
difference in the work done;  eg. two of these were:

DO i = 2,n
if((gn(i,k)-yg)*(gn(i-1,k)-yg) > 0.d0) CYCLE
....

and

sign0 = SIGN(1.0, gn(1,k)-yg)
DO i = 2,n
if((gn(i,k)-yg)*sign0 > 0.d0) CYCLE
sign0 = -sign0
....

which eliminates the "(gn(i-1,k)-yg)" subtraction, but has minimal
impact on the CPU time.

Looks like the above two options are hitting rock bottom CPU
time-wise.








Report this thread to moderator Post Follow-up to this message
Old Post
dud_address@xparadise.net.nz
08-18-04 08:58 PM


Re: Bit intrinsic to extract sign of a real number - possible?
On Thu, 19 Aug 2004 00:47:39 +1200, dud_address@xparadise.net.nz
wrote:

.....
>
>** I actually tried about 3 variations of the real*real code & they
>consistently resulted in the same CPU time, despite apparent
>difference in the work done;  eg. two of these were:
>
>DO i = 2,n
>      if((gn(i,k)-yg)*(gn(i-1,k)-yg) > 0.d0) CYCLE
>     .....
>
>and
>
>sign0 = SIGN(1.0, gn(1,k)-yg)
>DO i = 2,n
>     if((gn(i,k)-yg)*sign0 > 0.d0) CYCLE
>     sign0 = -sign0
>    .....
>
>which eliminates the "(gn(i-1,k)-yg)" subtraction, but has minimal
>impact on the CPU time.
>
>Looks like the above two options are hitting rock bottom CPU
>time-wise.

In fact, under repeated testing, the second option does show a slight
performance gain ( 0 to 10%) over the first.

D


Report this thread to moderator Post Follow-up to this message
Old Post
dud_address@xparadise.net.nz
08-18-04 08:58 PM


Re: Bit intrinsic to extract sign of a real number - possible?
dud_address@xparadise.net.nz writes:

> Looks like James' comments about near zero cost of real multiplication
> might be close to the mark **

Yep.  James is almost always worth listening to.

I've been "doing" computers for 35 years now and I've learned a
lesson that many have also learned before me: some things change.
Although there are certainly enduring principles, details like
"floating point operations are expensive" aren't among them.
Floating point used to be such a big deal that you'd often see
performance figures expressed in FLOPS (floating point operations
per second).  Well, you still see it, but it just doesn't mean
as much any more.  Memory access seems to be one of the big
factors today.  Tomorrow maybe something different.

That's one of the factors that drives my interest in standards.

With fair regularity, younger folk at Dryden are surprised when I
start advocating something different from what I did before.
Sometimes the older ones are surprised also, but if so, it is
because they've forgotten all the previous times I also changed
positions.  No, I no longer think that a CDC mainframe is the
best choice for our engineering applications; that's a postion
that I held pretty strongly in the mid 70's.

My most recent change was to break down and buy ATA disks instead of
SCSI ones for desktops.  I won't care about the better performance of
the fast SCSI disks if I can't hear any more because of their darned
noise level; I can buy some pretty quiet ATA ones.  My priorities for
system requirements have changed.

--
Richard Maine                       |  Good judgment comes from experience;
email: my first.last at org.domain  |  experience comes from bad judgment.
org: nasa, domain: gov              |        -- Mark Twain

Report this thread to moderator Post Follow-up to this message
Old Post
Richard Maine
08-18-04 08:58 PM


Re: Bit intrinsic to extract sign of a real number - possible?
Richard Maine wrote:
> dud_address@xparadise.net.nz writes:
>
> 
>
>
> Yep.  James is almost always worth listening to.
>
> I've been "doing" computers for 35 years now and I've learned a
> lesson that many have also learned before me: some things change.
> Although there are certainly enduring principles, details like
> "floating point operations are expensive" aren't among them.
> Floating point used to be such a big deal that you'd often see
> performance figures expressed in FLOPS (floating point operations
> per second).  Well, you still see it, but it just doesn't mean
> as much any more.  Memory access seems to be one of the big
> factors today.  Tomorrow maybe something different.
>
> That's one of the factors that drives my interest in standards.
>
> With fair regularity, younger folk at Dryden are surprised when I
> start advocating something different from what I did before.
> Sometimes the older ones are surprised also, but if so, it is
> because they've forgotten all the previous times I also changed
> positions.  No, I no longer think that a CDC mainframe is the
> best choice for our engineering applications; that's a postion
> that I held pretty strongly in the mid 70's.
>
> My most recent change was to break down and buy ATA disks instead of
> SCSI ones for desktops.  I won't care about the better performance of
> the fast SCSI disks if I can't hear any more because of their darned
> noise level; I can buy some pretty quiet ATA ones.  My priorities for
> system requirements have changed.
>

Surely in another 10 years or so, Father Time will have cured your
problem hearing noisy disks?

*ducks*

cheers,

Rich

--
Dr Richard H D Townsend
Bartol Research Institute
University of Delaware

[ Delete VOID for valid email address ]

Report this thread to moderator Post Follow-up to this message
Old Post
Rich Townsend
08-18-04 08:58 PM


Re: Bit intrinsic to extract sign of a real number - possible?
Rich Townsend <rhdt@barVOIDtol.udel.edu> writes:

> Surely in another 10 years or so, Father Time will have cured your
> problem hearing noisy disks?

Eh?  :-)

> *ducks*

Quack.  :-)

--
Richard Maine                       |  Good judgment comes from experience;
email: my first.last at org.domain  |  experience comes from bad judgment.
org: nasa, domain: gov              |        -- Mark Twain

Report this thread to moderator Post Follow-up to this message
Old Post
Richard Maine
08-18-04 08:59 PM


Re: Bit intrinsic to extract sign of a real number - possible?
dud_address@xparadise.net.nz wrote in message news:<u9j5i0l40udqrbl0nt5qrcq8lgu1nv2u0m@4ax.
com>...
> Need to detect when a (real 8) number changes sign.  Seems the most
> efficient way should be to test the bit that defines whether the
> number is pos or neg?  However, all the BIT funtiions (apart from
> TRANSFER) seem to operate only on integers.  Surely there is a way to
> extract the bit that sets +/- for a real number.
>
> My current code is along the lines (a = real 8)
>
>
> DO i = 2,n
>     if(a(i)*a(i-1) > 0.d0) CYCLE  ! say 90% of cases
>     .... do some minor stuff (one statement)
> END DO
>
>
> That requires a real*real & i-1 operation for every case.
>
> I can use SIGN, but in timinig tests that worked out a lot slower than
> the current code.    If they were integer(8) numbers, the test I
> envisage would be along the lines:
>
>
> logical(1) no_change
> integer(8), allocatable :: num(:)
> integer(4) i, n

Attention:  kind constants are not portable !!

> ALLOCATE( num( ...) )
>
> no_change = BTEST (num(1), 63)
> DO i = 2,n
>     if( BTEST (num(i), 63) == no_change) CYCLE

Attention(2):  comparison of Logical quantities requires .EQV. operator
in stead of ==   !!

[JvO]

>     no_change = .NOT.no_change
>     .... do some stuff
> END DO
>
>
> Anything equivalent I could use for real numbers?

If you want to avoid TRANSFER you might use EQUIVALENCE

integer :: a  !  Simplified to single precision.
real  :: b
equivalence (a, b)
read *, b
if (btest(a, 31) ) ...

!!  I just wonder if this is really faster than
if( b < 0.0) ...
!! I am rather sure that testing  a(i) * a(i-1) is (much) slower than
retaining pos. or neg. in a logical variable.

[JvO]

Report this thread to moderator Post Follow-up to this message
Old Post
jan van oosterwijk
08-18-04 08:59 PM


Re: Bit intrinsic to extract sign of a real number - possible?
On 18 Aug 2004 10:00:10 -0700, jvo_36@hotmail.com (jan van oosterwijk)
wrote:

 
>
>Attention(2):  comparison of Logical quantities requires .EQV. operator
>in stead of ==   !!
>
>  [JvO]

Oops.  Must be an IVF8 extension, because == works.

In fact, in this case, there is about a 5% performance gain over the
whole task (determining points in polygons), simply by using == rather
than .EQV. in the one line of code (suggests a heavy performance hit
on that one line).

Still probably not a good idea if it is non-standard, but it does
raise an interesting question; ie. why is .EQV. a lot slower than ==?
Scarcely an inducement to be "standards compliant", especially since
the code will never see the light of electrons on any VAX(!) -
"in-house" code only.

Anyway, as below, bit testing is not the fastest option for this
application.



>!! I am rather sure that testing  a(i) * a(i-1) is (much) slower than
>retaining pos. or neg. in a logical variable.
>
>[JvO]

As I noted in another post in this thread, the real situation was
slightly more "complex", in that "a(i)" was actually "gn(i,k)-yg".
That required an extra line "gn8 = gn(i,k)-yg" before the logical test
(with gn8 equivalenced to in8).  In this situation, the logical bit
test option turns out to be 40%-50% SLOWER than testing real*real -
esp when the second real is a +/- toggle switch (only change when
"gn(i,k)-yg" changes sign).

Even without the extra line of code, bit testing is unlikely provide
any worthwhile performance gain as the real*real seems to be costing
next to no CPU time on my system.

David


Report this thread to moderator Post Follow-up to this message
Old Post
dud_address@xparadise.net.nz
08-19-04 01:58 AM


Sponsored Links




Last Thread Next Thread Next
Pages (2): [1] 2 »
Search this forum -> 
Post New Thread

Fortran archive

Show a Printable Version Send to friend Email This Page to Someone! subscribe to this thread Receive updates to this thread
Computer Consultants
Programming Jobs
Visual Basic Controls
SQL Server Programming
Webservices
Java Security
Visual Studio
C# Programming
Visual J++
Software engineering
Open source Software
Perl Programming
PHP Programming
ASP Programming
ASP .NET Programming
Visual Basic Programming
Windows Scripting Host
Java Programming
Java Help
Java Beans
VBScript
Cobol
MAC Applications
Unix Programming
Forum Jump:
All times are GMT. The time now is 01:14 PM.

 

Programming forum archive

Copyrights CodeComments.com 2004 - 2006

Powered by vBulletin Copyright 2000-2006 Jelsoft Enterprises Limited.