2007-08-23 23:43:48

by Luka Napotnik

[permalink] [raw]
Subject: division and cpu usage

Hello.

I'm new to kernel development and have some questions.

1. Why can't I divide with regular casting to double ((double)a /
(double)b)? It gives me strange errors when compiling:

WARNING: "__divdf3" [/root....] undefined!
WARNING: "__addf3" [/root/...] undefined!
WARNING: "__floatsidf" [/root/...] undefined!

And if I compile with normal integers, I get zero as the result.

2. I'm trying to get the percentage of CPU used for a certain
task_struct and figured the following formula:

(task->utime + task->stime) / jiffies

Before calculating I convert all the variables to jiffies. Is this correct?

Please help.

Greets,
Lukla


2007-08-24 01:05:08

by David Schwartz

[permalink] [raw]
Subject: RE: division and cpu usage


> Hello.
>
> I'm new to kernel development and have some questions.
>
> 1. Why can't I divide with regular casting to double ((double)a /
> (double)b)? It gives me strange errors when compiling:
>
> WARNING: "__divdf3" [/root....] undefined!
> WARNING: "__addf3" [/root/...] undefined!
> WARNING: "__floatsidf" [/root/...] undefined!
>
> And if I compile with normal integers, I get zero as the result.

As the HOWTO says:

"The kernel is written using GNU C and the GNU toolchain. While it
adheres to the ISO C89 standard, it uses a number of extensions that are
not featured in the standard. The kernel is a freestanding C
environment, with no reliance on the standard C library, so some
portions of the C standard are not supported. Arbitrary long long
divisions and floating point are not allowed. It can sometimes be
difficult to understand the assumptions the kernel has on the toolchain
and the extensions that it uses, and unfortunately there is no
definitive reference for them. Please check the gcc info pages (`info
gcc`) for some information on them."

The short version is simply that it's very expensive to allow this, adding
overhead even in cases where it isn't used, and there is very little
benefit. For almost every imaginable case where you would want floating
point in the kernel, fixed point works as well or better.

Just scale your numbers by shifting them.

DS


2007-08-24 11:35:07

by linux-os (Dick Johnson)

[permalink] [raw]
Subject: Re: division and cpu usage


On Thu, 23 Aug 2007, Luka Napotnik wrote:
> Hello.
>
> I'm new to kernel development and have some questions.
>
> 1. Why can't I divide with regular casting to double ((double)a /
> (double)b)? It gives me strange errors when compiling:
>
> WARNING: "__divdf3" [/root....] undefined!
> WARNING: "__addf3" [/root/...] undefined!
> WARNING: "__floatsidf" [/root/...] undefined!
>
> And if I compile with normal integers, I get zero as the result.
>
> 2. I'm trying to get the percentage of CPU used for a certain
> task_struct and figured the following formula:
>
> (task->utime + task->stime) / jiffies
>
> Before calculating I convert all the variables to jiffies. Is this correct?
>
> Please help.
>
> Greets,
> Lukla

Floating point operations are not allowed in the kernel. Often,
when you think you are simply creating a constant, the compiler
generates runtime code so you have to watch out for that as well.

You can use "long long" for high precision math if necessary.

Cheers,
Dick Johnson
Penguin : Linux version 2.6.22.1 on an i686 machine (5588.30 BogoMips).
My book : http://www.AbominableFirebug.com/
_


****************************************************************
The information transmitted in this message is confidential and may be privileged. Any review, retransmission, dissemination, or other use of this information by persons or entities other than the intended recipient is prohibited. If you are not the intended recipient, please notify Analogic Corporation immediately - by replying to this message or by sending an email to [email protected] - and destroy all copies of this information, including any attachments, without reading or disclosing them.

Thank you.

2007-08-24 12:47:32

by Jan Engelhardt

[permalink] [raw]
Subject: Re: division and cpu usage


On Aug 24 2007 07:34, linux-os (Dick Johnson) wrote:
>> I'm new to kernel development and have some questions.
>>
>> 1. Why can't I divide with regular casting to double ((double)a /
>> (double)b)? It gives me strange errors when compiling:
>>
>> WARNING: "__divdf3" [/root....] undefined!
>> WARNING: "__addf3" [/root/...] undefined!
>> WARNING: "__floatsidf" [/root/...] undefined!
>>
>> And if I compile with normal integers, I get zero as the result.
>>
>> 2. I'm trying to get the percentage of CPU used for a certain
>> task_struct and figured the following formula:
>>
>> (task->utime + task->stime) / jiffies
>>
>> Before calculating I convert all the variables to jiffies. Is this correct?

* So use integer math: (task->utime + task->stime) * 100 / jiffies
and you get the 'common' percentage. In integer, that is.

* I am not sure about the use of jiffies when it comes to CONFIG_NO_HZ=y.

>Floating point operations are not allowed in the kernel. Often,

IIRC they are allowed since ... recently (2.6.16, .17? can't remember). When
the kernel tries to execute an FP instruction (and traps as a result), more
kernel code will enable that the FP stack gets properly switched when a process
changes between userspace-kernelspace.

>You can use "long long" for high precision math if necessary.

That will give link failure for __udivdi3. Use do_div().


Jan
--

2007-08-25 23:25:52

by Luka Napotnik

[permalink] [raw]
Subject: Re: division and cpu usage

Hello again.

I have the following code:
========================================
clock_t c_sum, j, p;
cputime_t j_tmp;
...
c_sum = cputime64_to_clock_t(task->utime) +
cputime64_to_clock_t(task->stime);
cur_j = jiffies;
j_tmp = jiffies64_to_cputime64(cur_j);
j = cputime64_to_clock_t(j_tmp);
p = (c_sum * 100) / j;
========================================

And if I check the p value of a certain process it gives wrong results.
For example for a process using 99% of the CPU it shows 20. What am I
doing wrong?

Greets,
Luka

Jan Engelhardt pravi:
> On Aug 24 2007 07:34, linux-os (Dick Johnson) wrote:
>>> I'm new to kernel development and have some questions.
>>>
>>> 1. Why can't I divide with regular casting to double ((double)a /
>>> (double)b)? It gives me strange errors when compiling:
>>>
>>> WARNING: "__divdf3" [/root....] undefined!
>>> WARNING: "__addf3" [/root/...] undefined!
>>> WARNING: "__floatsidf" [/root/...] undefined!
>>>
>>> And if I compile with normal integers, I get zero as the result.
>>>
>>> 2. I'm trying to get the percentage of CPU used for a certain
>>> task_struct and figured the following formula:
>>>
>>> (task->utime + task->stime) / jiffies
>>>
>>> Before calculating I convert all the variables to jiffies. Is this correct?
>
> * So use integer math: (task->utime + task->stime) * 100 / jiffies
> and you get the 'common' percentage. In integer, that is.
>
> * I am not sure about the use of jiffies when it comes to CONFIG_NO_HZ=y.
>
>> Floating point operations are not allowed in the kernel. Often,
>
> IIRC they are allowed since ... recently (2.6.16, .17? can't remember). When
> the kernel tries to execute an FP instruction (and traps as a result), more
> kernel code will enable that the FP stack gets properly switched when a process
> changes between userspace-kernelspace.
>
>> You can use "long long" for high precision math if necessary.
>
> That will give link failure for __udivdi3. Use do_div().
>
>
> Jan

2007-08-27 22:07:32

by Luka Napotnik

[permalink] [raw]
Subject: Re: division and cpu usage

Jan Engelhardt pravi:
> On Aug 24 2007 07:34, linux-os (Dick Johnson) wrote:
>>> I'm new to kernel development and have some questions.
>>>
>>> 1. Why can't I divide with regular casting to double ((double)a /
>>> (double)b)? It gives me strange errors when compiling:
>>>
>>> WARNING: "__divdf3" [/root....] undefined!
>>> WARNING: "__addf3" [/root/...] undefined!
>>> WARNING: "__floatsidf" [/root/...] undefined!
>>>
>>> And if I compile with normal integers, I get zero as the result.
>>>
>>> 2. I'm trying to get the percentage of CPU used for a certain
>>> task_struct and figured the following formula:
>>>
>>> (task->utime + task->stime) / jiffies

This formula just doesn't work. I have a task with 99% CPU (top) but the
result of that formula is random (4, sometimes 8). What am I doing
wrong? Please help.

>>>
>>> Before calculating I convert all the variables to jiffies. Is this correct?
>
> * So use integer math: (task->utime + task->stime) * 100 / jiffies
> and you get the 'common' percentage. In integer, that is.
>
> * I am not sure about the use of jiffies when it comes to CONFIG_NO_HZ=y.
>
>> Floating point operations are not allowed in the kernel. Often,
>
> IIRC they are allowed since ... recently (2.6.16, .17? can't remember). When
> the kernel tries to execute an FP instruction (and traps as a result), more
> kernel code will enable that the FP stack gets properly switched when a process
> changes between userspace-kernelspace.
>
>> You can use "long long" for high precision math if necessary.
>
> That will give link failure for __udivdi3. Use do_div().
>
>
> Jan

2007-08-28 06:45:17

by Jan Engelhardt

[permalink] [raw]
Subject: Re: division and cpu usage


On Aug 28 2007 00:07, Luka Napotnik wrote:
>>>> 2. I'm trying to get the percentage of CPU used for a certain
>>>> task_struct and figured the following formula:
>>>>
>>>> (task->utime + task->stime) / jiffies
>
>This formula just doesn't work. I have a task with 99% CPU (top) but the
>result of that formula is random (4, sometimes 8). What am I doing
>wrong? Please help.

You are calculating the CPU time the process has used since the start.
That is definitely not the same as the "%CPU" that top shows, more like
the "TIME+" top shows by default.

2007-08-28 10:41:50

by Luka Napotnik

[permalink] [raw]
Subject: Re: division and cpu usage

How about this:
===============================
old_stime = task->stime;
old_utime = task->utime
old_j = jiffies;

set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(1 * HZ);

new_stime = task->stime;
new_utime = task->utime;
new_j = jiffies;
sum = ((new_stime - old_stime) + (new_utime - old_utime)) * 100 / (new_j
- old_j)
===============================

I get how much time the task has spent in 1 sec in the scheduler and
then get the percentage?

Greets,
Luka

Jan Engelhardt pravi:
> On Aug 28 2007 00:07, Luka Napotnik wrote:
>>>>> 2. I'm trying to get the percentage of CPU used for a certain
>>>>> task_struct and figured the following formula:
>>>>>
>>>>> (task->utime + task->stime) / jiffies
>> This formula just doesn't work. I have a task with 99% CPU (top) but the
>> result of that formula is random (4, sometimes 8). What am I doing
>> wrong? Please help.
>
> You are calculating the CPU time the process has used since the start.
> That is definitely not the same as the "%CPU" that top shows, more like
> the "TIME+" top shows by default.
>
>



Attachments:
signature.asc (252.00 B)
OpenPGP digital signature

2007-08-28 12:11:19

by Jan Engelhardt

[permalink] [raw]
Subject: Re: division and cpu usage


On Aug 28 2007 12:41, Luka Napotnik wrote:
>
>How about this:
>===============================
>old_stime = task->stime;
>old_utime = task->utime
>old_j = jiffies;
>
>set_current_state(TASK_INTERRUPTIBLE);
>schedule_timeout(1 * HZ);
>
>new_stime = task->stime;
>new_utime = task->utime;
>new_j = jiffies;
>sum = ((new_stime - old_stime) + (new_utime - old_utime)) * 100 / (new_j
>- old_j)
>===============================
>
>I get how much time the task has spent in 1 sec in the scheduler and
>then get the percentage?

Looks sane to me. Though you have to try. And, like I said before, be aware of
dynticks, so you might want to use something else than jiffies. Not sure what
the function was called though.

Jan
--