linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Floating point usage inside kernel
       [not found] <S1754322Ab1KYK6W/20111125105822Z+929@vger.kernel.org>
@ 2011-11-25 11:14 ` Nuno Santos
  2011-11-25 12:08   ` Jiri Slaby
  0 siblings, 1 reply; 9+ messages in thread
From: Nuno Santos @ 2011-11-25 11:14 UTC (permalink / raw)
  To: linux-kernel

Hi,

This question has probably bean discussed for several times in this list 
but the information I found googling around is inconclusive to me.

I'm implementing a kernel input driver and I have successfully achieved 
my goal for at least 75%.

Since I understand that kernel floating point usage is discouraged I 
have converted most of my code to use integers. I knew that kernel 
floating point usage was already discouraged in Windows but could be 
done by saving floating point unit state.

However, there is a small part of my code that really needs floating 
point calculations and it's conversion to integer is not being trivial.

Since that part of the code is not done intensively and since I have 
already found information that leads me to believe that the same is 
possible, that is, saving fpu state and successfully achieve floating 
point calculation on kernel.

I found this article on the internet which deeply explains fpu usage in 
kernel:

http://www.linuxsmiths.com/blog/?p=253

As a conclusion, the article says that if we need to use floating point 
calculations in kernel, it is possible if we keep the state of the fpu 
unit with the following calls:

*/kernel_fpu_begin()
/**/kernel_fpu_end()

We also need to use the compiler flag -mhard-float

But when I compile I get:

error: implicit declaration of function ‘kernel_fpu_begin’ 
[-Werror=implicit-function-declaration]
error: implicit declaration of function ‘kernel_fpu_end’ 
[-Werror=implicit-function-declaration]

Doing a grep -r kernel_fpu_begin * on kernel source dir I can find 
several references to this functions but not them is included in the 
include dir. Which include do I need to have this functions found in 
compile time?

Am I even sailing in the right direction? Is this really possible or am 
I wasting my time?

I'm new to kernel programming and this is not a trivial issue for me. I 
hope you understand.

Thanks,

With my best regards,

Nuno Santos
/*

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 11:14 ` Floating point usage inside kernel Nuno Santos
@ 2011-11-25 12:08   ` Jiri Slaby
  2011-11-25 16:16     ` Nuno Santos
  0 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2011-11-25 12:08 UTC (permalink / raw)
  To: Nuno Santos; +Cc: linux-kernel

On 11/25/2011 12:14 PM, Nuno Santos wrote:
> Doing a grep -r kernel_fpu_begin * on kernel source dir I can find
> several references to this functions but not them is included in the
> include dir. Which include do I need to have this functions found in
> compile time?

It is defined in arch specific includes. For x86 in asm/i387.h (in
arch/x86/include).

> Am I even sailing in the right direction?

You should generally not use that anyway. It's not portable and disables
preemption.

Can't you do the computations in userspace? And why it cannot be
switched to integer types -- what algorithm is that? Some math function?

reagards,
-- 
js

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 12:08   ` Jiri Slaby
@ 2011-11-25 16:16     ` Nuno Santos
  2011-11-25 17:05       ` Paulo Marques
  2011-11-28  4:00       ` Andy Lutomirski
  0 siblings, 2 replies; 9+ messages in thread
From: Nuno Santos @ 2011-11-25 16:16 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: linux-kernel

Hi Jiri,

Thanks for your reply.

The algorithm is a matrix transform computation to make a affine a 
geometric transform.

Basicly it is based on the following functions:

http://pastebin.com/YHzYuLPU

Curiously I ran a test before writing this email and guest what.... is 
working!! :)

But now that I have opened this question here I should ask... is it safe?

This is the call to the function i'm making in kernel side (most of the 
computation are made in userspace during a calibration and only 
calculated data goest back to kernel. Then, in runtime inside the driver 
I need to call this function:

mx3d_transform(src, zone->Matrix, tex);

Which is defined in the pastebin above.

And the input data is the following:

src[0] = [0,6300]; src[1] = [0,6300]; src[2] = 1.0;
zone->Matrix (double[3][3])

u: 492.188 v: 615.234 sx: 683.158 sy: 5790.13

u: 5807.81 v: 615.234 sx: 5944.9 sy: 5900.58

u: 5807.81 v: 5684.77 sx: 6027.46 sy: 560.337

u: 492.188 v: 5684.77 sx: 751.198 sy: 476.455


and tex is output (double[3])

I'm not protecting the call to the function with kernel_fpu_begin and 
kernel_fpu_end

Should I be happy with the results or should I be concerned in 
converting this function only to integer?

I hope I have been clear in my language.

Thanks,

With my best regards,

Nuno

On 11/25/2011 12:08 PM, Jiri Slaby wrote:
> On 11/25/2011 12:14 PM, Nuno Santos wrote:
>> Doing a grep -r kernel_fpu_begin * on kernel source dir I can find
>> several references to this functions but not them is included in the
>> include dir. Which include do I need to have this functions found in
>> compile time?
> It is defined in arch specific includes. For x86 in asm/i387.h (in
> arch/x86/include).
>
>> Am I even sailing in the right direction?
> You should generally not use that anyway. It's not portable and disables
> preemption.
>
> Can't you do the computations in userspace? And why it cannot be
> switched to integer types -- what algorithm is that? Some math function?
>
> reagards,



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 16:16     ` Nuno Santos
@ 2011-11-25 17:05       ` Paulo Marques
  2011-11-25 17:46         ` Nuno Santos
  2011-11-28  4:00       ` Andy Lutomirski
  1 sibling, 1 reply; 9+ messages in thread
From: Paulo Marques @ 2011-11-25 17:05 UTC (permalink / raw)
  To: Nuno Santos; +Cc: Jiri Slaby, linux-kernel

Nuno Santos wrote:
> Hi Jiri,

Hi, Nuno

> [...]
> But now that I have opened this question here I should ask... is it safe?

No!

> [...]
> And the input data is the following:
> 
> src[0] = [0,6300]; src[1] = [0,6300]; src[2] = 1.0;
> zone->Matrix (double[3][3])
> 
> u: 492.188 v: 615.234 sx: 683.158 sy: 5790.13
> 
> u: 5807.81 v: 615.234 sx: 5944.9 sy: 5900.58
> 
> u: 5807.81 v: 5684.77 sx: 6027.46 sy: 560.337
> 
> u: 492.188 v: 5684.77 sx: 751.198 sy: 476.455
> 
> 
> and tex is output (double[3])
[...]

Given the range of numbers you're working with, you can probably get
away with just a 16.16 fixed point representation. The operations go
like this:

convert a double to a fixed point number just do (but not on the kernel):

  fixed = (s32)(double * 65536.0);

convert an integer to fixed:

  fixed = integer << 16;

multiplication:

  result = (s32)(((s64) fixed_a * fixed_b) >> 16);

addition:

  result = fixed_a + fixed_b;

etc...

Unless you have overflow or need more than 16 bits of fractional
precision, you'll have no problem with this approach.

I hope this helps,

-- 
Paulo Marques - www.grupopie.com

"All generalizations are false."

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 17:05       ` Paulo Marques
@ 2011-11-25 17:46         ` Nuno Santos
  2011-11-25 18:10           ` Paulo Marques
  0 siblings, 1 reply; 9+ messages in thread
From: Nuno Santos @ 2011-11-25 17:46 UTC (permalink / raw)
  To: Paulo Marques; +Cc: Jiri Slaby, linux-kernel

>
> Given the range of numbers you're working with, you can probably get
> away with just a 16.16 fixed point representation. The operations go
> like this:
>
> convert a double to a fixed point number just do (but not on the kernel):
>
>    fixed = (s32)(double * 65536.0);
>
> convert an integer to fixed:
>
>    fixed = integer<<  16;
>
> multiplication:
>
>    result = (s32)(((s64) fixed_a * fixed_b)>>  16);
>
> addition:
>
>    result = fixed_a + fixed_b;
>
> etc...
>
> Unless you have overflow or need more than 16 bits of fractional
> precision, you'll have no problem with this approach.
>
> I hope this helps,
Sorry, i'm not sure if I have completely understand your suggestion. Are 
you telling me to apply this transform only to my input data, or to all 
the operations that are applied in the function used in kernel?

Thanks,

With my best regards,

Nuno

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 17:46         ` Nuno Santos
@ 2011-11-25 18:10           ` Paulo Marques
  2011-11-28 10:11             ` Nuno Santos
  0 siblings, 1 reply; 9+ messages in thread
From: Paulo Marques @ 2011-11-25 18:10 UTC (permalink / raw)
  To: Nuno Santos; +Cc: Jiri Slaby, linux-kernel

Nuno Santos wrote:
>>[...]
>> Unless you have overflow or need more than 16 bits of fractional
>> precision, you'll have no problem with this approach.
>>
>> I hope this helps,
> Sorry, i'm not sure if I have completely understand your suggestion. Are
> you telling me to apply this transform only to my input data, or to all
> the operations that are applied in the function used in kernel?

Imagine that your matrix coefficients are:

 2.5,     1, 4.7
45.3, 0.765,  10
   0,     0,   1

and your input is:

3420.56, 5410.76, 1

You start by converting the matrix coefficients:

2.5 * 65536.0 = 163840
....

so the matrix becomes:

 163840 65536 308019
2968781 50135 655360
      0     0  65536

This can be done in userspace and the coefficients can be sent to the
kernel as fixed point numbers.

You do the same (this time on the kernel) with your input, so it becomes:

224169820 354599567 65536

Now you can do:

q[0] = fixed_mul(p[0], a[0][0]) + fixed_mul(p[1], a[1][0]) +
fixed_mul(p[2], a[2][0]);
....

where "fixed_mul" is a function that does the multiplication as I
explained earlier.

To convert the result back to an integer, just shift down by 16.

-- 
Paulo Marques - www.grupopie.com

"Feed the hungry, save the whales, free the mallocs!"

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 16:16     ` Nuno Santos
  2011-11-25 17:05       ` Paulo Marques
@ 2011-11-28  4:00       ` Andy Lutomirski
  1 sibling, 0 replies; 9+ messages in thread
From: Andy Lutomirski @ 2011-11-28  4:00 UTC (permalink / raw)
  To: Nuno Santos; +Cc: Jiri Slaby, linux-kernel

On 11/25/2011 08:16 AM, Nuno Santos wrote:
> Hi Jiri,
> 
> Thanks for your reply.
> 
> The algorithm is a matrix transform computation to make a affine a
> geometric transform.
> 
> Basicly it is based on the following functions:
> 
> http://pastebin.com/YHzYuLPU
> 
> Curiously I ran a test before writing this email and guest what.... is
> working!! :)
> 
> But now that I have opened this question here I should ask... is it safe?

[...]

> I'm not protecting the call to the function with kernel_fpu_begin and
> kernel_fpu_end

It's not safe even if you do protect it with kernel_fpu_begin.  On
x86-64, a userspace process that mucks with MXCSR can trivially cause
you to oops even if you use kernel_fpu_begin.  (I'm pretty sure x86-32
has a similar issue, and I imagine that other architectures have related
issues.)  This might change someday, but there are exactly zero use
cases outside staging, so don't hold your breath.

--Andy

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-25 18:10           ` Paulo Marques
@ 2011-11-28 10:11             ` Nuno Santos
  2011-11-28 12:50               ` Paulo Marques
  0 siblings, 1 reply; 9+ messages in thread
From: Nuno Santos @ 2011-11-28 10:11 UTC (permalink / raw)
  To: Paulo Marques; +Cc: linux-kernel

Ok, understood!

Just one more question. To do this, do I need to change the data type 
from double to int?

Thanks,

Nuno

On 11/25/2011 06:10 PM, Paulo Marques wrote:
> Nuno Santos wrote:
>>> [...]
>>> Unless you have overflow or need more than 16 bits of fractional
>>> precision, you'll have no problem with this approach.
>>>
>>> I hope this helps,
>> Sorry, i'm not sure if I have completely understand your suggestion. Are
>> you telling me to apply this transform only to my input data, or to all
>> the operations that are applied in the function used in kernel?
> Imagine that your matrix coefficients are:
>
>   2.5,     1, 4.7
> 45.3, 0.765,  10
>     0,     0,   1
>
> and your input is:
>
> 3420.56, 5410.76, 1
>
> You start by converting the matrix coefficients:
>
> 2.5 * 65536.0 = 163840
> ....
>
> so the matrix becomes:
>
>   163840 65536 308019
> 2968781 50135 655360
>        0     0  65536
>
> This can be done in userspace and the coefficients can be sent to the
> kernel as fixed point numbers.
>
> You do the same (this time on the kernel) with your input, so it becomes:
>
> 224169820 354599567 65536
>
> Now you can do:
>
> q[0] = fixed_mul(p[0], a[0][0]) + fixed_mul(p[1], a[1][0]) +
> fixed_mul(p[2], a[2][0]);
> ....
>
> where "fixed_mul" is a function that does the multiplication as I
> explained earlier.
>
> To convert the result back to an integer, just shift down by 16.
>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Floating point usage inside kernel
  2011-11-28 10:11             ` Nuno Santos
@ 2011-11-28 12:50               ` Paulo Marques
  0 siblings, 0 replies; 9+ messages in thread
From: Paulo Marques @ 2011-11-28 12:50 UTC (permalink / raw)
  To: Nuno Santos; +Cc: linux-kernel

Nuno Santos wrote:
> Ok, understood!
> 
> Just one more question. To do this, do I need to change the data type
> from double to int?

You shouldn't have any "double" declarations on kernel code or the
compiler might start using floating point instructions to handle it.

Things that the compiler can work out at compile time are probably ok,
like converting constants:

#define FIXED(a)   (s32)((a) * 65536.0)

fixed = FIXED(1.25);

In this case compiler should make all the calculations at compile time
and replace the macro "FIXED(1.25)" with the integer 81920.

-- 
Paulo Marques - www.grupopie.com

"Don't worry, you'll be fine; I saw it work in a cartoon once..."

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-11-28 12:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <S1754322Ab1KYK6W/20111125105822Z+929@vger.kernel.org>
2011-11-25 11:14 ` Floating point usage inside kernel Nuno Santos
2011-11-25 12:08   ` Jiri Slaby
2011-11-25 16:16     ` Nuno Santos
2011-11-25 17:05       ` Paulo Marques
2011-11-25 17:46         ` Nuno Santos
2011-11-25 18:10           ` Paulo Marques
2011-11-28 10:11             ` Nuno Santos
2011-11-28 12:50               ` Paulo Marques
2011-11-28  4:00       ` Andy Lutomirski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).