* 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 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
* 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
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