Skip to content

Loss of precision in all single precision workspace queries, implicit and explicit #600

@oxydicer

Description

@oxydicer

Hello everybody,

recently I stumbled across an error when using ssyevd via the lapacke interface.
It points to a problem in the lapack interface in general. It goes like this:

According the the lapack standard interface, many routines like ssyevd you have to call twice:
Once for asking the routine how much scratch memory it needs for a certain matrix size,
and only then call the routine in earnest with the required scratch memory sections
as parameters.

If you look closely at this first call, which should return the required memory size, e.g.
for a routine like ssyevd, you see that even according to the lapack documentation,
the memory requirement is passed back via a pointer to a float value.
So when calculating the memory it goes through a series of values:

calculate memory       ->    store value in reference   ->  retrieve the value for use (allocation)
    int64                            float                              int64

It is int64 is in case of an ilp64 interface, otherwise it would be int32.
So in essence, we have an intermediary shortening of the memory value from
63 bit to 24 bit !!!
(or more precise, to 24bit between the outermost set bits in IEEE 754 float representation)
Even in the case of 32bit integers, you have a shortening of 31 bits to 24 bits.

So, if you would call the memory requirement calculation as in the past 'by hand'
you might have chance to see where it goes wrong, but still you cannot prevent the shorting
to a float value. If you use the automatic memory allocation via the modern lapacke interface
you don't even have an idea what could be wrong, as the routine advertises to take care
of all memory management by itself!

This happens in all single precision routines (s/c) in lapack, which calculate
the memory requirement as an intermediary step.
Switching to double precison would then use a double precision reference instead,
increasing the intermediary value to 53 bits instead, which is still not close to the 64 bits
one would assume with a 64bit interface.

Workaround, four possible ways:

  1. If you want to use single or complex lapack routines, do not use the automatic memory allocation via the C lapacke interface
  2. If you use the two-call lapack function method, for the memory calculation use the double(!) routine
  3. Have a look at the reference implementation of the lapack routine and calculate the required memory on your own
  4. Only use small matrix sizes when using float/complex matrices

Other people have stumbled upon this, but didn't follow it through to the real cause, e.g.
openBLAS build with int64 support fails on valid input for ssyevd

One has to stress, that at least with the two-call method, this is not a bug, but a design flaw.
In case of the lapacke automatic memory allocation, it has to be considered a fairly severe bug.

Regards,

oxydicer

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions