Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys/frac: Integer fractions #9283

Merged
merged 1 commit into from
Dec 9, 2019
Merged

sys/frac: Integer fractions #9283

merged 1 commit into from
Dec 9, 2019

Conversation

jnohlgard
Copy link
Member

Contribution description

Introduces the frac library for integer scaling by semi-constant fractions. The implementation is based around the libdivide integer division library (https://libdivide.com) which uses the multiplicative inverse to compute integer division. The parameters required can be computed at runtime, or optionally pre-configured at compile time. A helper application (tests/frac-config) is provided to generate static configurations.
A benchmark application (tests/bench_frac_div) is provided to compare the different division methods (div module, frac module, division operator), both using constant fractions and runtime variable fractions.

The intended use case is a better timer algorithm with runtime adjustable tick conversion frequency for improved clock synchronization between nodes.

Libdivide is imported as a copy from the official repo, instead of as a git pkg, since the library is a single header file and I believe this functionality will become quite central to many applications and we don't want to require a network connection to build this. This will be refactored into a pkg with a locally cached copy of the header.

Issues/PRs references

Similar but different use case: #9280

@jnohlgard jnohlgard added State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet Type: new feature The issue requests / The PR implemements a new feature for RIOT Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR labels Jun 4, 2018
@ZetaR60
Copy link
Contributor

ZetaR60 commented Jun 4, 2018

I feel that this is a superior approach to what I was working on in #9280. I was considering fractions rather than simple reciprocals as one method to fix the precision problem with 512/15625 (which results in a major loss in precision in #9280 currently). Timer tick conversion was also the main reason I rewrote sys/div.h. In my opinion, if this PR works well for the task then it should supersede #9280, and sys/div.h in general.

@jnohlgard
Copy link
Member Author

Div is still faster during execution, but with the drawback that the fraction must be a compile time constant.
@ZetaR60 could you try the benchmark app on your atmega board?
I only have numbers from Cortex-M CPUs

@ZetaR60
Copy link
Contributor

ZetaR60 commented Jun 5, 2018

Here is some output from the benchmark test. I had to change TEST_NUMOF to 512 to get it to fit in ram. It would be interesting to see the difference between the old div behavior and #9280.

[liveuser@localhost-live bench_frac_div]$ make BOARD=mega-xplained term
/home/liveuser/Desktop/RIOT-pr-frac/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600"
No handlers could be found for logger "root"
2018-06-05 19:41:20,501 - INFO # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2018-06-05 19:41:22,403 - INFO # 

2018-06-05 19:41:22,471 - INFO # main(): This is RIOT! (Version: UNKNOWN (builddir: /home/liveuser/Desktop/RIOT-pr-frac))
2018-06-05 19:41:22,473 - INFO # Division benchmark
2018-06-05 19:41:22,475 - INFO # Init timer
2018-06-05 19:41:22,504 - INFO # TIM_REF_DEV: 0
2018-06-05 19:41:22,506 - INFO # TIM_REF_FREQ: 1000000
2018-06-05 19:41:22,606 - INFO # Warning! spurious timer interrupt
2018-06-05 19:41:23,504 - INFO # const (  512 /   15625) /,%:    27355 frac:    34424 div:    48527
2018-06-05 19:41:24,503 - INFO # var ( 999321 / 1000000) /,%:    18322 frac:    33020 div:    62779
2018-06-05 19:41:25,204 - INFO # var (1000000 /  999321) /,%:    18403 frac:    33021 div: [no implementation]
2018-06-05 19:41:26,107 - INFO # const (  512 /   15625) /,%:    28041 frac:    34425 div:    15199
2018-06-05 19:41:27,204 - INFO # var ( 999322 / 1000000) /,%:    18325 frac:    31524 div:    62780
2018-06-05 19:41:27,905 - INFO # var (1000000 /  999322) /,%:    18304 frac:    40690 div: [no implementation]
2018-06-05 19:41:28,804 - INFO # const (  512 /   15625) /,%:    28185 frac:    34417 div:    15202
2018-06-05 19:41:29,774 - INFO # var ( 999323 / 1000000) /,%:    18531 frac:    33025 div:    62782
2018-06-05 19:41:30,504 - INFO # var (1000000 /  999323) /,%:    18646 frac:    42206 div: [no implementation]
2018-06-05 19:41:31,404 - INFO # const (  512 /   15625) /,%:    27725 frac:    34426 div:    15205
2018-06-05 19:41:32,505 - INFO # var ( 999324 / 1000000) /,%:    18134 frac:    29991 div:    62785
2018-06-05 19:41:33,206 - INFO # var (1000000 /  999324) /,%:    18338 frac:    39136 div: [no implementation]
2018-06-05 19:41:34,105 - INFO # const (  512 /   15625) /,%:    27656 frac:    34426 div:    15202
2018-06-05 19:41:35,104 - INFO # var ( 999325 / 1000000) /,%:    18173 frac:    37565 div:    62783
2018-06-05 19:41:35,804 - INFO # var (1000000 /  999325) /,%:    18306 frac:    37534 div: [no implementation]
2018-06-05 19:41:36,704 - INFO # const (  512 /   15625) /,%:    27284 frac:    34418 div:    15204
2018-06-05 19:41:37,805 - INFO # var ( 999326 / 1000000) /,%:    18454 frac:    31504 div:    62786
2018-06-05 19:41:38,506 - INFO # var (1000000 /  999326) /,%:    18404 frac:    31503 div: [no implementation]
2018-06-05 19:41:39,405 - INFO # const (  512 /   15625) /,%:    27857 frac:    34422 div:    15200
2018-06-05 19:41:40,404 - INFO # var ( 999327 / 1000000) /,%:    18790 frac:    33023 div:    62782
2018-06-05 19:41:41,104 - INFO # var (1000000 /  999327) /,%:    18692 frac:    33003 div: [no implementation]
2018-06-05 19:41:42,004 - INFO # const (  512 /   15625) /,%:    27669 frac:    34417 div:    15202
2018-06-05 19:41:43,105 - INFO # var ( 999328 / 1000000) /,%:    18323 frac:    35978 div:    62785
2018-06-05 19:41:43,807 - INFO # var (1000000 /  999328) /,%:    18235 frac:    45127 div: [no implementation]
2018-06-05 19:41:44,706 - INFO # const (  512 /   15625) /,%:    26507 frac:    34418 div:    15202
2018-06-05 19:41:45,704 - INFO # var ( 999329 / 1000000) /,%:    18058 frac:    33023 div:    62781
2018-06-05 19:41:46,504 - INFO # var (1000000 /  999329) /,%:    18148 frac:    42210 div: [no implementation]
2018-06-05 19:41:47,304 - INFO # const (  512 /   15625) /,%:    27578 frac:    34426 div:    15206
2018-06-05 19:41:48,405 - INFO # var ( 999330 / 1000000) /,%:    18085 frac:    37584 div:    62788
2018-06-05 19:41:49,107 - INFO # var (1000000 /  999330) /,%:    18278 frac:    28462 div: [no implementation]
2018-06-05 19:41:50,006 - INFO # const (  512 /   15625) /,%:    27686 frac:    34412 div:    15200
2018-06-05 19:41:51,004 - INFO # var ( 999331 / 1000000) /,%:    18208 frac:    33023 div:    62784
2018-06-05 19:41:51,804 - INFO # var (1000000 /  999331) /,%:    17996 frac:    33000 div: [no implementation]
2018-06-05 19:41:52,604 - INFO # const (  512 /   15625) /,%:    27572 frac:    34421 div:    15205
2018-06-05 19:41:53,705 - INFO # var ( 999332 / 1000000) /,%:    18453 frac:    29987 div:    62788
2018-06-05 19:41:54,406 - INFO # var (1000000 /  999332) /,%:    18484 frac:    29978 div: [no implementation]
2018-06-05 19:41:55,305 - INFO # const (  512 /   15625) /,%:    28235 frac:    34421 div:    15201
2018-06-05 19:41:56,304 - INFO # var ( 999333 / 1000000) /,%:    18462 frac:    33021 div:    62785
2018-06-05 19:41:57,005 - INFO # var (1000000 /  999333) /,%:    18613 frac:    42183 div: [no implementation]
2018-06-05 19:41:57,904 - INFO # const (  512 /   15625) /,%:    28052 frac:    34422 div:    15206
2018-06-05 19:41:59,006 - INFO # var ( 999334 / 1000000) /,%:    18201 frac:    31504 div:    62786
2018-06-05 19:41:59,706 - INFO # var (1000000 /  999334) /,%:    18334 frac:    31536 div: [no implementation]
2018-06-05 19:42:00,605 - INFO # const (  512 /   15625) /,%:    28426 frac:    34430 div:    15203
2018-06-05 19:42:01,604 - INFO # var ( 999335 / 1000000) /,%:    18454 frac:    39090 div:    62786
2018-06-05 19:42:02,304 - INFO # var (1000000 /  999335) /,%:    18563 frac:    29941 div: [no implementation]
2018-06-05 19:42:03,204 - INFO # const (  512 /   15625) /,%:    27720 frac:    34423 div:    15204
2018-06-05 19:42:04,306 - INFO # var ( 999336 / 1000000) /,%:    18200 frac:    28458 div:    62784
2018-06-05 19:42:05,005 - INFO # var (1000000 /  999336) /,%:    18325 frac:    37600 div: [no implementation]
2018-06-05 19:42:05,906 - INFO # const (  512 /   15625) /,%:    27437 frac:    34416 div:    15204
2018-06-05 19:42:06,904 - INFO # var ( 999337 / 1000000) /,%:    18372 frac:    33019 div:    62785
2018-06-05 19:42:07,704 - INFO # var (1000000 /  999337) /,%:    18334 frac:    42212 div: [no implementation]
2018-06-05 19:42:08,504 - INFO # const (  512 /   15625) /,%:    27716 frac:    34426 div:    15204
2018-06-05 19:42:09,606 - INFO # var ( 999338 / 1000000) /,%:    18702 frac:    31521 div:    62783
2018-06-05 19:42:10,307 - INFO # var (1000000 /  999338) /,%:    18880 frac:    40657 div: [no implementation]
2018-06-05 19:42:11,206 - INFO # const (  512 /   15625) /,%:    27991 frac:    34421 div:    15200
2018-06-05 19:42:12,204 - INFO # var ( 999339 / 1000000) /,%:    18241 frac:    33018 div:    62779
2018-06-05 19:42:13,005 - INFO # var (1000000 /  999339) /,%:    18406 frac:    42216 div: [no implementation]
2018-06-05 19:42:13,804 - INFO # const (  512 /   15625) /,%:    27868 frac:    34418 div:    15202
2018-06-05 19:42:14,874 - INFO # var ( 999340 / 1000000) /,%:    18023 frac:    46690 div:    62784
2018-06-05 19:42:15,605 - INFO # var (1000000 /  999340) /,%:    18019 frac:    46749 div: [no implementation]
2018-06-05 19:42:16,504 - INFO # const (  512 /   15625) /,%:    27541 frac:    34421 div:    15202
2018-06-05 19:42:17,606 - INFO # var ( 999341 / 1000000) /,%:    18526 frac:    33026 div:    62782
2018-06-05 19:42:18,307 - INFO # var (1000000 /  999341) /,%:    18476 frac:    42204 div: [no implementation]
2018-06-05 19:42:19,206 - INFO # const (  512 /   15625) /,%:    27867 frac:    34420 div:    15205
2018-06-05 19:42:20,204 - INFO # var ( 999342 / 1000000) /,%:    18313 frac:    31512 div:    62787
2018-06-05 19:42:20,905 - INFO # var (1000000 /  999342) /,%:    18139 frac:    31503 div: [no implementation]
2018-06-05 19:42:21,804 - INFO # const (  512 /   15625) /,%:    28336 frac:    34427 div:    15206
2018-06-05 19:42:22,905 - INFO # var ( 999343 / 1000000) /,%:    18574 frac:    33028 div:    62792
2018-06-05 19:42:23,607 - INFO # var (1000000 /  999343) /,%:    18553 frac:    42203 div: [no implementation]
2018-06-05 19:42:24,506 - INFO # const (  512 /   15625) /,%:    27745 frac:    34426 div:    15205
2018-06-05 19:42:25,504 - INFO # var ( 999344 / 1000000) /,%:    18530 frac:    37550 div:    62788
2018-06-05 19:42:26,304 - INFO # var (1000000 /  999344) /,%:    18683 frac:    37504 div: [no implementation]
2018-06-05 19:42:27,104 - INFO # const (  512 /   15625) /,%:    27835 frac:    34421 div:    15201
2018-06-05 19:42:28,207 - INFO # var ( 999345 / 1000000) /,%:    18225 frac:    39095 div:    62784
2018-06-05 19:42:28,904 - INFO # var (1000000 /  999345) /,%:    18086 frac:    39092 div: [no implementation]
2018-06-05 19:42:29,807 - INFO # const (  512 /   15625) /,%:    27709 frac:    34423 div:    15204
2018-06-05 19:42:30,904 - INFO # var ( 999346 / 1000000) /,%:    18358 frac:    31517 div:    62787
2018-06-05 19:42:31,606 - INFO # var (1000000 /  999346) /,%:    18257 frac:    40632 div: [no implementation]
2018-06-05 19:42:32,505 - INFO # const (  512 /   15625) /,%:    28318 frac:    34425 div:    15204
2018-06-05 19:42:33,508 - INFO # var ( 999347 / 1000000) /,%:    18563 frac:    33030 div:    62786
2018-06-05 19:42:34,205 - INFO # var (1000000 /  999347) /,%:    18442 frac:    42181 div: [no implementation]
2018-06-05 19:42:35,104 - INFO # const (  512 /   15625) /,%:    28433 frac:    34430 div:    15205
2018-06-05 19:42:36,205 - INFO # var ( 999348 / 1000000) /,%:    18667 frac:    29995 div:    62785
2018-06-05 19:42:36,906 - INFO # var (1000000 /  999348) /,%:    18461 frac:    29962 div: [no implementation]
2018-06-05 19:42:37,805 - INFO # const (  512 /   15625) /,%:    28034 frac:    34424 div:    15206
2018-06-05 19:42:38,774 - INFO # var ( 999349 / 1000000) /,%:    18431 frac:    33027 div:    62790
2018-06-05 19:42:39,505 - INFO # var (1000000 /  999349) /,%:    18377 frac:    42198 div: [no implementation]
2018-06-05 19:42:40,404 - INFO # const (  512 /   15625) /,%:    27481 frac:    34418 div:    15202
2018-06-05 19:42:41,506 - INFO # var ( 999350 / 1000000) /,%:    18416 frac:    36012 div:    62784
2018-06-05 19:42:42,207 - INFO # var (1000000 /  999350) /,%:    18212 frac:    36009 div: [no implementation]
2018-06-05 19:42:43,105 - INFO # const (  512 /   15625) /,%:    27594 frac:    34427 div:    15202
2018-06-05 19:42:44,104 - INFO # var ( 999351 / 1000000) /,%:    18373 frac:    33025 div:    62785
2018-06-05 19:42:44,804 - INFO # var (1000000 /  999351) /,%:    18609 frac:    42208 div: [no implementation]
2018-06-05 19:42:45,704 - INFO # const (  512 /   15625) /,%:    28111 frac:    34422 div:    15203
2018-06-05 19:42:46,806 - INFO # var ( 999352 / 1000000) /,%:    18725 frac:    28455 div:    62785
2018-06-05 19:42:47,506 - INFO # var (1000000 /  999352) /,%:    18520 frac:    28413 div: [no implementation]
2018-06-05 19:42:48,406 - INFO # const (  512 /   15625) /,%:    28100 frac:    34421 div:    15202
2018-06-05 19:42:49,404 - INFO # var ( 999353 / 1000000) /,%:    18357 frac:    33029 div:    62783
2018-06-05 19:42:50,105 - INFO # var (1000000 /  999353) /,%:    18293 frac:    33002 div: [no implementation]
2018-06-05 19:42:51,004 - INFO # const (  512 /   15625) /,%:    27548 frac:    34421 div:    15203
2018-06-05 19:42:52,106 - INFO # var ( 999354 / 1000000) /,%:    18422 frac:    31510 div:    62780
2018-06-05 19:42:52,806 - INFO # var (1000000 /  999354) /,%:    18447 frac:    31517 div: [no implementation]
2018-06-05 19:42:53,705 - INFO # const (  512 /   15625) /,%:    27389 frac:    34420 div:    15203
2018-06-05 19:42:54,704 - INFO # var ( 999355 / 1000000) /,%:    18227 frac:    39095 div:    62784
2018-06-05 19:42:55,405 - INFO # var (1000000 /  999355) /,%:    18221 frac:    39154 div: [no implementation]
2018-06-05 19:42:56,304 - INFO # const (  512 /   15625) /,%:    27917 frac:    34420 div:    15201
2018-06-05 19:42:57,406 - INFO # var ( 999356 / 1000000) /,%:    18156 frac:    29982 div:    62782
2018-06-05 19:42:58,107 - INFO # var (1000000 /  999356) /,%:    18027 frac:    29982 div: [no implementation]
2018-06-05 19:42:59,005 - INFO # const (  512 /   15625) /,%:    27785 frac:    34423 div:    15204
2018-06-05 19:43:00,004 - INFO # var ( 999357 / 1000000) /,%:    18212 frac:    33027 div:    62789
2018-06-05 19:43:00,705 - INFO # var (1000000 /  999357) /,%:    18205 frac:    42157 div: [no implementation]
2018-06-05 19:43:01,604 - INFO # const (  512 /   15625) /,%:    27656 frac:    34422 div:    15202
2018-06-05 19:43:02,706 - INFO # var ( 999358 / 1000000) /,%:    18195 frac:    31513 div:    62782
2018-06-05 19:43:03,407 - INFO # var (1000000 /  999358) /,%:    18162 frac:    40682 div: [no implementation]
2018-06-05 19:43:04,306 - INFO # const (  512 /   15625) /,%:    28119 frac:    34419 div:    15204
2018-06-05 19:43:05,304 - INFO # var ( 999359 / 1000000) /,%:    18479 frac:    33018 div:    62784
2018-06-05 19:43:06,104 - INFO # var (1000000 /  999359) /,%:    18484 frac:    42181 div: [no implementation]
2018-06-05 19:43:06,904 - INFO # const (  512 /   15625) /,%:    27300 frac:    34428 div:    15202
2018-06-05 19:43:08,005 - INFO # var ( 999360 / 1000000) /,%:    18235 frac:    40496 div:    62785
2018-06-05 19:43:08,705 - INFO # var (1000000 /  999360) /,%:    18205 frac:    31373 div: [no implementation]
2018-06-05 19:43:09,605 - INFO # const (  512 /   15625) /,%:    27896 frac:    34421 div:    15205
2018-06-05 19:43:10,604 - INFO # var ( 999361 / 1000000) /,%:    18509 frac:    33023 div:    62784
2018-06-05 19:43:11,404 - INFO # var (1000000 /  999361) /,%:    18566 frac:    33033 div: [no implementation]
2018-06-05 19:43:12,204 - INFO # const (  512 /   15625) /,%:    27692 frac:    34425 div:    15207
2018-06-05 19:43:13,305 - INFO # var ( 999362 / 1000000) /,%:    18140 frac:    31511 div:    62789
2018-06-05 19:43:14,008 - INFO # var (1000000 /  999362) /,%:    18237 frac:    31467 div: [no implementation]
2018-06-05 19:43:14,907 - INFO # const (  512 /   15625) /,%:    28115 frac:    34424 div:    15202
2018-06-05 19:43:15,904 - INFO # var ( 999363 / 1000000) /,%:    18257 frac:    33025 div:    62784
2018-06-05 19:43:16,705 - INFO # var (1000000 /  999363) /,%:    17974 frac:    42206 div: [no implementation]
2018-06-05 19:43:17,504 - INFO # const (  512 /   15625) /,%:    27822 frac:    34424 div:    15202
2018-06-05 19:43:18,607 - INFO # var ( 999364 / 1000000) /,%:    18017 frac:    29985 div:    62781
2018-06-05 19:43:19,307 - INFO # var (1000000 /  999364) /,%:    18225 frac:    30005 div: [no implementation]
2018-06-05 19:43:20,206 - INFO # const (  512 /   15625) /,%:    27852 frac:    34422 div:    15205
2018-06-05 19:43:21,204 - INFO # var ( 999365 / 1000000) /,%:    18493 frac:    39094 div:    62786
2018-06-05 19:43:22,005 - INFO # var (1000000 /  999365) /,%:    18482 frac:    39148 div: [no implementation]
2018-06-05 19:43:22,804 - INFO # const (  512 /   15625) /,%:    27277 frac:    34426 div:    15205
2018-06-05 19:43:23,907 - INFO # var ( 999366 / 1000000) /,%:    18501 frac:    31516 div:    62788
2018-06-05 19:43:24,608 - INFO # var (1000000 /  999366) /,%:    18358 frac:    31502 div: [no implementation]
2018-06-05 19:43:25,507 - INFO # const (  512 /   15625) /,%:    27352 frac:    34416 div:    15200
2018-06-05 19:43:26,504 - INFO # var ( 999367 / 1000000) /,%:    18222 frac:    33017 div:    62783
2018-06-05 19:43:27,305 - INFO # var (1000000 /  999367) /,%:    18183 frac:    33048 div: [no implementation]
2018-06-05 19:43:28,104 - INFO # const (  512 /   15625) /,%:    28703 frac:    34421 div:    15205
2018-06-05 19:43:29,207 - INFO # var ( 999368 / 1000000) /,%:    18428 frac:    28456 div:    62787
2018-06-05 19:43:29,908 - INFO # var (1000000 /  999368) /,%:    18298 frac:    37593 div: [no implementation]
2018-06-05 19:43:30,807 - INFO # const (  512 /   15625) /,%:    27856 frac:    34420 div:    15203
2018-06-05 19:43:31,804 - INFO # var ( 999369 / 1000000) /,%:    18566 frac:    33023 div:    62784
2018-06-05 19:43:32,605 - INFO # var (1000000 /  999369) /,%:    18390 frac:    42162 div: [no implementation]
2018-06-05 19:43:33,405 - INFO # const (  512 /   15625) /,%:    27187 frac:    34420 div:    15206
2018-06-05 19:43:34,508 - INFO # var ( 999370 / 1000000) /,%:    18350 frac:    37588 div:    62787
2018-06-05 19:43:35,205 - INFO # var (1000000 /  999370) /,%:    18491 frac:    37633 div: [no implementation]
2018-06-05 19:43:36,108 - INFO # const (  512 /   15625) /,%:    28055 frac:    34425 div:    15204
2018-06-05 19:43:37,205 - INFO # var ( 999371 / 1000000) /,%:    18409 frac:    33028 div:    62787
2018-06-05 19:43:37,906 - INFO # var (1000000 /  999371) /,%:    18564 frac:    42172 div: [no implementation]
2018-06-05 19:43:38,805 - INFO # const (  512 /   15625) /,%:    28346 frac:    34419 div:    15200
2018-06-05 19:43:39,809 - INFO # var ( 999372 / 1000000) /,%:    18399 frac:    29985 div:    62781
2018-06-05 19:43:40,505 - INFO # var (1000000 /  999372) /,%:    18384 frac:    29983 div: [no implementation]
2018-06-05 19:43:41,408 - INFO # const (  512 /   15625) /,%:    28036 frac:    34417 div:    15202
2018-06-05 19:43:42,505 - INFO # var ( 999373 / 1000000) /,%:    18324 frac:    33016 div:    62784
2018-06-05 19:43:43,206 - INFO # var (1000000 /  999373) /,%:    18421 frac:    33030 div: [no implementation]
2018-06-05 19:43:44,105 - INFO # const (  512 /   15625) /,%:    27581 frac:    34420 div:    15199
2018-06-05 19:43:45,108 - INFO # var ( 999374 / 1000000) /,%:    18524 frac:    31510 div:    62779
2018-06-05 19:43:45,804 - INFO # var (1000000 /  999374) /,%:    18141 frac:    31489 div: [no implementation]
2018-06-05 19:43:46,708 - INFO # const (  512 /   15625) /,%:    28169 frac:    34423 div:    15199
2018-06-05 19:43:47,805 - INFO # var ( 999375 / 1000000) /,%:    18365 frac:    39020 div:    62779
2018-06-05 19:43:48,507 - INFO # var (1000000 /  999375) /,%:    18390 frac:    38995 div: [no implementation]
2018-06-05 19:43:49,405 - INFO # const (  512 /   15625) /,%:    27843 frac:    34429 div:    15204
2018-06-05 19:43:50,405 - INFO # var ( 999376 / 1000000) /,%:    18323 frac:    37553 div:    62787
2018-06-05 19:43:51,105 - INFO # var (1000000 /  999376) /,%:    18497 frac:    37513 div: [no implementation]
2018-06-05 19:43:52,005 - INFO # const (  512 /   15625) /,%:    28096 frac:    34429 div:    15201
2018-06-05 19:43:53,106 - INFO # var ( 999377 / 1000000) /,%:    18375 frac:    33033 div:    62781
2018-06-05 19:43:53,807 - INFO # var (1000000 /  999377) /,%:    18424 frac:    42152 div: [no implementation]
2018-06-05 19:43:54,706 - INFO # const (  512 /   15625) /,%:    27450 frac:    34427 div:    15207
2018-06-05 19:43:55,705 - INFO # var ( 999378 / 1000000) /,%:    18288 frac:    31518 div:    62787
2018-06-05 19:43:56,405 - INFO # var (1000000 /  999378) /,%:    18462 frac:    31547 div: [no implementation]
2018-06-05 19:43:57,305 - INFO # const (  512 /   15625) /,%:    27989 frac:    34422 div:    15205
2018-06-05 19:43:58,406 - INFO # var ( 999379 / 1000000) /,%:    18257 frac:    33023 div:    62782
2018-06-05 19:43:59,107 - INFO # var (1000000 /  999379) /,%:    18266 frac:    42186 div: [no implementation]
2018-06-05 19:44:00,006 - INFO # const (  512 /   15625) /,%:    27295 frac:    34424 div:    15204
2018-06-05 19:44:01,005 - INFO # var ( 999380 / 1000000) /,%:    18082 frac:    46695 div:    62785
2018-06-05 19:44:01,805 - INFO # var (1000000 /  999380) /,%:    18234 frac:    37556 div: [no implementation]
2018-06-05 19:44:02,605 - INFO # const (  512 /   15625) /,%:    27562 frac:    34421 div:    15202
2018-06-05 19:44:03,705 - INFO # var ( 999381 / 1000000) /,%:    17980 frac:    33025 div:    62783
2018-06-05 19:44:04,406 - INFO # var (1000000 /  999381) /,%:    18314 frac:    32989 div: [no implementation]
2018-06-05 19:44:05,305 - INFO # const (  512 /   15625) /,%:    28369 frac:    34413 div:    15202
2018-06-05 19:44:06,305 - INFO # var ( 999382 / 1000000) /,%:    18429 frac:    31509 div:    62783
2018-06-05 19:44:07,106 - INFO # var (1000000 /  999382) /,%:    18573 frac:    40652 div: [no implementation]
2018-06-05 19:44:07,905 - INFO # const (  512 /   15625) /,%:    27881 frac:    34426 div:    15207
2018-06-05 19:44:09,008 - INFO # var ( 999383 / 1000000) /,%:    18354 frac:    33028 div:    62790
2018-06-05 19:44:09,709 - INFO # var (1000000 /  999383) /,%:    18266 frac:    33028 div: [no implementation]
2018-06-05 19:44:10,607 - INFO # const (  512 /   15625) /,%:    27297 frac:    34424 div:    15206
2018-06-05 19:44:11,605 - INFO # var ( 999384 / 1000000) /,%:    18134 frac:    28463 div:    62787
2018-06-05 19:44:12,405 - INFO # var (1000000 /  999384) /,%:    18236 frac:    37638 div: [no implementation]
2018-06-05 19:44:13,203 - INFO # Exiting Pyterm

[liveuser@localhost-live bench_frac_div]$

@jnohlgard
Copy link
Member Author

jnohlgard commented Jun 7, 2018

It is surprising to see that the division operator is so much faster than the other methods on atmega. Do they have hardware division?

Here are some numbers for mulle (Cortex-M4), note how the relative performance between the different methods is reversed compared to atmega:

2018-06-08 07:27:18,078 - INFO # const (  512 /   15625) /,%:    25886 frac:    22017 div:     8194 double:    44055
2018-06-08 07:27:18,193 - INFO # var ( 999355 / 1000000) /,%:    43902 frac:    23553 div:    17068 double:    44055
2018-06-08 07:27:18,257 - INFO # var (1000000 /  999355) /,%:    26504 frac:    23553 div:   N/A    double:    44055
2018-06-08 07:27:18,369 - INFO # const (  512 /   15625) /,%:    25882 frac:    22017 div:     8194 double:    44047
2018-06-08 07:27:18,481 - INFO # var ( 999356 / 1000000) /,%:    43896 frac:    22017 div:    17068 double:    44047
2018-06-08 07:27:18,545 - INFO # var (1000000 /  999356) /,%:    26574 frac:    22017 div:   N/A    double:    44047
2018-06-08 07:27:18,656 - INFO # const (  512 /   15625) /,%:    25888 frac:    22017 div:     8193 double:    44051
2018-06-08 07:27:18,783 - INFO # var ( 999357 / 1000000) /,%:    43902 frac:    22017 div:    17068 double:    44051
2018-06-08 07:27:18,831 - INFO # var (1000000 /  999357) /,%:    26624 frac:    23553 div:   N/A    double:    44051
2018-06-08 07:27:18,945 - INFO # const (  512 /   15625) /,%:    25885 frac:    22017 div:     8193 double:    44043
2018-06-08 07:27:19,073 - INFO # var ( 999358 / 1000000) /,%:    43893 frac:    22017 div:    17068 double:    44043
2018-06-08 07:27:19,135 - INFO # var (1000000 /  999358) /,%:    26685 frac:    23553 div:   N/A    double:    44043
2018-06-08 07:27:19,247 - INFO # const (  512 /   15625) /,%:    25888 frac:    22017 div:     8193 double:    44044
2018-06-08 07:27:19,361 - INFO # var ( 999359 / 1000000) /,%:    43891 frac:    22017 div:    17068 double:    44044
2018-06-08 07:27:19,425 - INFO # var (1000000 /  999359) /,%:    26766 frac:    23553 div:   N/A    double:    44044
2018-06-08 07:27:19,537 - INFO # const (  512 /   15625) /,%:    25886 frac:    22017 div:     8193 double:    44050
2018-06-08 07:27:19,663 - INFO # var ( 999360 / 1000000) /,%:    43901 frac:    23553 div:    17067 double:    44050
2018-06-08 07:27:19,713 - INFO # var (1000000 /  999360) /,%:    25748 frac:    22017 div:   N/A    double:    44050
2018-06-08 07:27:19,826 - INFO # const (  512 /   15625) /,%:    25886 frac:    22017 div:     8193 double:    44042
2018-06-08 07:27:19,951 - INFO # var ( 999361 / 1000000) /,%:    43890 frac:    22017 div:    17067 double:    44042
2018-06-08 07:27:19,999 - INFO # var (1000000 /  999361) /,%:    25841 frac:    22017 div:   N/A    double:    44042
2018-06-08 07:27:20,111 - INFO # const (  512 /   15625) /,%:    25884 frac:    22017 div:     8193 double:    44047
2018-06-08 07:27:20,239 - INFO # var ( 999362 / 1000000) /,%:    43895 frac:    22017 div:    17068 double:    44047
2018-06-08 07:27:20,287 - INFO # var (1000000 /  999362) /,%:    25915 frac:    22017 div:   N/A    double:    44047
2018-06-08 07:27:20,399 - INFO # const (  512 /   15625) /,%:    25885 frac:    22016 div:     8193 double:    44044
2018-06-08 07:27:20,529 - INFO # var ( 999363 / 1000000) /,%:    43892 frac:    22017 div:    17068 double:    44044

Edit: Updated with float test

@jnohlgard
Copy link
Member Author

jnohlgard commented Jun 7, 2018

and some numbers for frdm-kw41z (Cortex-M0+), note that the compiler bundled division function is significantly slower here than on CM4:

2018-06-08 07:22:25,120 - INFO # const (  512 /   15625) /,%:   136058 frac:    87179 div:    30061 double:   228206
2018-06-08 07:22:25,678 - INFO # var ( 999594 / 1000000) /,%:   237749 frac:    87207 div:    66681 double:   228206
2018-06-08 07:22:25,920 - INFO # var (1000000 /  999594) /,%:   133186 frac:    89686 div:   N/A    double:   228206
2018-06-08 07:22:26,435 - INFO # const (  512 /   15625) /,%:   135965 frac:    87182 div:    30062 double:   228033
2018-06-08 07:22:26,995 - INFO # var ( 999595 / 1000000) /,%:   238278 frac:    89686 div:    66682 double:   228033
2018-06-08 07:22:27,235 - INFO # var (1000000 /  999595) /,%:   133179 frac:    87126 div:   N/A    double:   228033
2018-06-08 07:22:27,750 - INFO # const (  512 /   15625) /,%:   135963 frac:    87183 div:    30063 double:   228209
2018-06-08 07:22:28,307 - INFO # var ( 999596 / 1000000) /,%:   237938 frac:    87220 div:    66683 double:   228209
2018-06-08 07:22:28,550 - INFO # var (1000000 /  999596) /,%:   133048 frac:    89857 div:   N/A    double:   228209
2018-06-08 07:22:29,064 - INFO # const (  512 /   15625) /,%:   135961 frac:    87180 div:    30061 double:   227811
2018-06-08 07:22:29,622 - INFO # var ( 999597 / 1000000) /,%:   237999 frac:    87206 div:    66681 double:   227811
2018-06-08 07:22:29,865 - INFO # var (1000000 /  999597) /,%:   133156 frac:    89828 div:   N/A    double:   227811
2018-06-08 07:22:30,379 - INFO # const (  512 /   15625) /,%:   136028 frac:    87184 div:    30063 double:   228163
2018-06-08 07:22:30,937 - INFO # var ( 999598 / 1000000) /,%:   238131 frac:    87210 div:    66683 double:   228163
2018-06-08 07:22:31,177 - INFO # var (1000000 /  999598) /,%:   133178 frac:    87135 div:   N/A    double:   228163
2018-06-08 07:22:31,691 - INFO # const (  512 /   15625) /,%:   135982 frac:    87184 div:    30063 double:   227858
2018-06-08 07:22:32,249 - INFO # var ( 999599 / 1000000) /,%:   238151 frac:    87222 div:    66682 double:   227858
2018-06-08 07:22:32,490 - INFO # var (1000000 /  999599) /,%:   133306 frac:    87185 div:   N/A    double:   227858
2018-06-08 07:22:33,004 - INFO # const (  512 /   15625) /,%:   135939 frac:    87184 div:    30062 double:   228014
2018-06-08 07:22:33,562 - INFO # var ( 999600 / 1000000) /,%:   238339 frac:    87185 div:    66681 double:   228014
2018-06-08 07:22:33,802 - INFO # var (1000000 /  999600) /,%:   133109 frac:    87293 div:   N/A    double:   228014
2018-06-08 07:22:34,316 - INFO # const (  512 /   15625) /,%:   135996 frac:    87182 div:    30072 double:   228113
2018-06-08 07:22:34,874 - INFO # var ( 999601 / 1000000) /,%:   238009 frac:    87206 div:    66681 double:   228113
2018-06-08 07:22:35,117 - INFO # var (1000000 /  999601) /,%:   133164 frac:    89886 div:   N/A    double:   228113
2018-06-08 07:22:35,631 - INFO # const (  512 /   15625) /,%:   136041 frac:    87179 div:    30059 double:   228051
2018-06-08 07:22:36,189 - INFO # var ( 999602 / 1000000) /,%:   238001 frac:    87207 div:    66678 double:   228051
2018-06-08 07:22:36,432 - INFO # var (1000000 /  999602) /,%:   133262 frac:    89916 div:   N/A    double:   228051
2018-06-08 07:22:36,946 - INFO # const (  512 /   15625) /,%:   136091 frac:    87181 div:    30063 double:   228010
2018-06-08 07:22:37,505 - INFO # var ( 999603 / 1000000) /,%:   238497 frac:    87205 div:    66683 double:   228010
2018-06-08 07:22:37,748 - INFO # var (1000000 /  999603) /,%:   133243 frac:    89686 div:   N/A    double:   228010

Edit: Updated output to include float test

@ZetaR60
Copy link
Contributor

ZetaR60 commented Jun 7, 2018

ATmega does have some support for division: FMUL - Fractional Multiply Unsigned, FMULS - Fractional Multiply Signed, FMULSU - Fractional Multiply Signed with Unsigned. I had not noticed this before. Neat!

@jnohlgard
Copy link
Member Author

Added one more benchmark for a scaling via 64 bit float. It is a lot slower on CM0+, but fast on big CPUs.
Here are some stats from a modern linux system (2.7 GHz Intel Skylake):

const (  512 /   15625) /,%:       90 frac:      284 div:      131 double:       58
var ( 999756 / 1000000) /,%:       59 frac:      264 div:      252 double:       58
var (1000000 /  999756) /,%:       73 frac:      369 div:   N/A    double:       58
const (  512 /   15625) /,%:       74 frac:      397 div:      115 double:       95
var ( 999757 / 1000000) /,%:       60 frac:      264 div:      276 double:       95
var (1000000 /  999757) /,%:       73 frac:      342 div:   N/A    double:       95
const (  512 /   15625) /,%:       73 frac:      264 div:      103 double:       58
var ( 999758 / 1000000) /,%:       56 frac:      387 div:      276 double:       58
var (1000000 /  999758) /,%:      102 frac:      289 div:   N/A    double:       58
const (  512 /   15625) /,%:       68 frac:      247 div:      102 double:       55
var ( 999759 / 1000000) /,%:       68 frac:      307 div:      252 double:       55
var (1000000 /  999759) /,%:       74 frac:      308 div:   N/A    double:       55
const (  512 /   15625) /,%:       69 frac:      326 div:      149 double:       75
var ( 999760 / 1000000) /,%:       60 frac:      261 div:      356 double:       75
var (1000000 /  999760) /,%:       73 frac:      277 div:   N/A    double:       75
const (  512 /   15625) /,%:       74 frac:      265 div:      106 double:       58
var ( 999761 / 1000000) /,%:       60 frac:      267 div:      226 double:       58
var (1000000 /  999761) /,%:       73 frac:      265 div:   N/A    double:       58
const (  512 /   15625) /,%:       73 frac:      265 div:       87 double:       58
var ( 999762 / 1000000) /,%:       59 frac:      300 div:      226 double:       58
var (1000000 /  999762) /,%:       73 frac:      268 div:   N/A    double:       58

@jnohlgard
Copy link
Member Author

@ZetaR60 btw, do the unittests for tests-frac and tests-div pass on atmega?

@ZetaR60
Copy link
Contributor

ZetaR60 commented Jun 9, 2018

@gebart The partial output of tests-frac is below. tests-div passes. There seems to be a bug in printf when trying to print 64-bit numbers (I had a similar issue when working on div)

[liveuser@localhost-live unittests]$ make BOARD=mega-xplained term
/home/liveuser/Desktop/RIOT-pr-frac/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "9600"
No handlers could be found for logger "root"
2018-06-08 20:10:25,740 - INFO # Connect to serial port /dev/ttyACM0
Welcome to pyterm!
Type '/exit' to exit.
2018-06-08 20:10:27,842 - INFO # 

2018-06-08 20:10:27,942 - INFO # main(): This is RIOT! (Version: UNKNOWN (builddir: /home/liveuser/Desktop/RIOT-pr-frac))
2018-06-08 20:10:29,410 - INFO # .Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:30,111 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:30,143 - INFO # Scaling overflow, skipping
2018-06-08 20:10:30,844 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:30,910 - INFO # Scaling overflow, skipping
2018-06-08 20:10:31,609 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:31,612 - INFO # Scaling overflow, skipping
2018-06-08 20:10:31,642 - INFO # Scaling overflow, skipping
2018-06-08 20:10:31,708 - INFO # Scaling overflow, skipping
2018-06-08 20:10:32,309 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:32,342 - INFO # Scaling overflow, skipping
2018-06-08 20:10:32,408 - INFO # Scaling overflow, skipping
2018-06-08 20:10:32,409 - INFO # Scaling overflow, skipping
2018-06-08 20:10:32,410 - INFO # Scaling overflow, skipping
2018-06-08 20:10:32,443 - INFO # Scaling overflow, skipping
2018-06-08 20:10:32,509 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,109 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:33,110 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,146 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,209 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,210 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,242 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,243 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,309 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,310 - INFO # Scaling overflow, skipping
2018-06-08 20:10:33,911 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:33,943 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,008 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,010 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,011 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,043 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,110 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,112 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,143 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,208 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,808 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:34,811 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,813 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,844 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,910 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,912 - INFO # Scaling overflow, skipping
2018-06-08 20:10:34,942 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,009 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,012 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,014 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,612 - INFO # Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling expect Scaling overflow, skipping
2018-06-08 20:10:35,643 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,708 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,710 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,711 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,744 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,810 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,812 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,843 - INFO # Scaling overflow, skipping
2018-06-08 20:10:35,908 - INFO # Scaling overflow, skipping

@ZetaR60
Copy link
Contributor

ZetaR60 commented Jun 9, 2018

Might be an instance of #1891

@jnohlgard
Copy link
Member Author

This implementation needs some work. To do items:

  • drop libdivide
  • optimize magic number to be the equivalent of num/den instead of 1/den
  • test feasibility of implementing 64, 32 and 16 bit using the same magic number constant with various shifts

@jnohlgard
Copy link
Member Author

The planned changes will make this implementation similar to what an optimized int * float -> int multiplication could look like

@smlng
Copy link
Member

smlng commented Jun 28, 2018

it might be easier to merge this if changes to xtimer are introduces in a separate PR. First having the frac module in without touching existing code will be safer - though I see the point in putting this to (good) use right away.

@jnohlgard
Copy link
Member Author

@smlng you are right. The unit tests should be enough in this PR

@jnohlgard
Copy link
Member Author

@ZetaR60 @smlng Updates:

  • Removed changes to xtimer (stashed for a future PR)
  • Not using libdivide anymore
  • Use uint32_t for both inputs and outputs
  • Only one multiplication and one right shift
  • Much faster execution
  • Some rounding errors are observed with certain combinations of input arguments to frac_scale.
  • Slightly slower than div, probably because of additional indirect memory access for the frac_t members.

The rounding errors occur when the implicit product (numerator * unscaled) is large (> 2**31). In comparison, libdivide performs some corrections for certain inputs to adjust the result, and I believe this observed rounding error is related to those adjustments. These adjustments have not been implemented here (both because of lacking time, and not fully understanding the mathematical proof).
So far the rounding errors are all of the category "rounded up instead of truncated towards zero". All rounding errors observed would have been fixed by decrementing the multiplier by one, but performing this decrement blindly introduces far more errors in the other direction.

Some useful papers for this topic, by one of the principal authors of GMP:
https://gmplib.org/~tege/divcnst-pldi94.pdf
https://gmplib.org/~tege/division-paper.pdf

@jnohlgard jnohlgard force-pushed the pr/frac branch 2 times, most recently from 246563b to 2ea5f4f Compare September 4, 2018 13:14
@RIOT-OS RIOT-OS deleted a comment Sep 5, 2018
@smlng
Copy link
Member

smlng commented Sep 5, 2018

Hi @gebart, here some test output run on STM32 Bluepill, it looks a bit weird but also regular with those periodic bursts of UINT32_MAX (4 trillion something) which I don't see in your sample output.

2018-09-05 08:47:13,656 - INFO # var (1000000 /  999447) /,%: 4294912151 frac:      996 div:   N/A    double:    19059
2018-09-05 08:47:13,698 - INFO # const (  512 /   15625) /,%:    10145 frac:      996 div:      769 double:    19081
2018-09-05 08:47:13,747 - INFO # var ( 999448 / 1000000) /,%:    10190 frac:      996 div:     8556 double:    19057
2018-09-05 08:47:13,789 - INFO # var (1000000 /  999448) /,%: 4294912164 frac:      996 div:   N/A    double:    19057
2018-09-05 08:47:13,831 - INFO # const (  512 /   15625) /,%:    10145 frac:      996 div:      768 double:    19085
2018-09-05 08:47:13,880 - INFO # var ( 999449 / 1000000) /,%:    10192 frac:      996 div:     8558 double:    19060
2018-09-05 08:47:13,921 - INFO # var (1000000 /  999449) /,%: 4294912200 frac:      996 div:   N/A    double:    19060
2018-09-05 08:47:13,964 - INFO # const (  512 /   15625) /,%:    10145 frac:      996 div:      769 double: 4294920842
2018-09-05 08:47:14,013 - INFO # var ( 999450 / 1000000) /,%:    10189 frac:      996 div:     8557 double:    19056
2018-09-05 08:47:14,055 - INFO # var (1000000 /  999450) /,%: 4294912219 frac:      996 div:   N/A    double:    19057
2018-09-05 08:47:14,097 - INFO # const (  512 /   15625) /,%:    10145 frac:      996 div:      769 double: 4294920845
2018-09-05 08:47:14,146 - INFO # var ( 999451 / 1000000) /,%:    10190 frac:      996 div:     8557 double:    19061
2018-09-05 08:47:14,187 - INFO # var (1000000 /  999451) /,%: 4294912236 frac:      996 div:   N/A    double:    19062
2018-09-05 08:47:14,230 - INFO # const (  512 /   15625) /,%:    10147 frac:      996 div:      768 double: 4294920843
2018-09-05 08:47:14,279 - INFO # var ( 999452 / 1000000) /,%:    10188 frac:      996 div:     8556 double:    19056
2018-09-05 08:47:14,320 - INFO # var (1000000 /  999452) /,%: 4294912281 frac:      996 div:   N/A    double:    19057
2018-09-05 08:47:14,363 - INFO # const (  512 /   15625) /,%:    10146 frac:      996 div:      769 double: 4294920842
2018-09-05 08:47:14,412 - INFO # var ( 999453 / 1000000) /,%:    10189 frac:      996 div:     8557 double:    19056
2018-09-05 08:47:14,453 - INFO # var (1000000 /  999453) /,%:    10536 frac: 4294902756 div:   N/A    double:    19056
2018-09-05 08:47:14,496 - INFO # const (  512 /   15625) /,%:    10147 frac:      996 div:      769 double: 4294920845
2018-09-05 08:47:14,546 - INFO # var ( 999454 / 1000000) /,%:    10189 frac:      996 div:     8557 double:    19060
2018-09-05 08:47:14,586 - INFO # var (1000000 /  999454) /,%:    10569 frac:      996 div:   N/A    double:    19060
2018-09-05 08:47:14,629 - INFO # const (  512 /   15625) /,%:    10145 frac:      997 div:      768 double: 4294920840
2018-09-05 08:47:14,678 - INFO # var ( 999455 / 1000000) /,%:    10189 frac:      996 div:     8556 double:    19057
2018-09-05 08:47:14,719 - INFO # var (1000000 /  999455) /,%:    10580 frac:      996 div:   N/A    double:    19055
2018-09-05 08:47:14,762 - INFO # const (  512 /   15625) /,%:    10146 frac:      996 div:      768 double: 4294920843
2018-09-05 08:47:14,812 - INFO # var ( 999456 / 1000000) /,%:    10190 frac:      996 div:     8556 double:    19057
2018-09-05 08:47:14,852 - INFO # var (1000000 /  999456) /,%:    10189 frac:      996 div:   N/A    double:    19057
2018-09-05 08:47:14,894 - INFO # const (  512 /   15625) /,%:    10146 frac:      996 div:      769 double: 4294920845
2018-09-05 08:47:14,944 - INFO # var ( 999457 / 1000000) /,%:    10189 frac:      996 div:     8557 double:    19059
2018-09-05 08:47:14,984 - INFO # var (1000000 /  999457) /,%:    10235 frac:      996 div:   N/A    double:    19058
2018-09-05 08:47:15,027 - INFO # const (  512 /   15625) /,%:    10147 frac:      996 div:      769 double: 4294920845
2018-09-05 08:47:15,076 - INFO # var ( 999458 / 1000000) /,%:    10190 frac:      996 div:     8557 double:    19059
2018-09-05 08:47:15,117 - INFO # var (1000000 /  999458) /,%:    10265 frac:      996 div:   N/A    double:    19060
2018-09-05 08:47:15,159 - INFO # const (  512 /   15625) /,%:    10146 frac:      996 div:      769 double: 4294920841
2018-09-05 08:47:15,209 - INFO # var ( 999459 / 1000000) /,%:    10191 frac:      996 div:     8556 double: 4294920816
2018-09-05 08:47:15,250 - INFO # var (1000000 /  999459) /,%:    10284 frac:      996 div:   N/A    double:    19056
2018-09-05 08:47:15,292 - INFO # const (  512 /   15625) /,%:    10145 frac:      996 div:      769 double: 4294920844
2018-09-05 08:47:15,342 - INFO # var ( 999460 / 1000000) /,%:    10190 frac:      996 div:     8557 double: 4294920817
2018-09-05 08:47:15,382 - INFO # var (1000000 /  999460) /,%:    10316 frac:      996 div:   N/A    double:    19057
2018-09-05 08:47:15,425 - INFO # const (  512 /   15625) /,%: 4294911907 frac:      996 div:      769 double:    19081
2018-09-05 08:47:15,475 - INFO # var ( 999461 / 1000000) /,%:    10191 frac:      996 div:     8557 double: 4294920816
2018-09-05 08:47:15,515 - INFO # var (1000000 /  999461) /,%:    10337 frac:      996 div:   N/A    double:    19055
2018-09-05 08:47:15,558 - INFO # const (  512 /   15625) /,%: 4294911906 frac:      996 div:      769 double:    19085
2018-09-05 08:47:15,607 - INFO # var ( 999462 / 1000000) /,%:    10190 frac:      997 div:     8556 double: 4294920821
2018-09-05 08:47:15,648 - INFO # var (1000000 /  999462) /,%:    10360 frac:      996 div:   N/A    double:    19060
2018-09-05 08:47:15,690 - INFO # const (  512 /   15625) /,%: 4294911906 frac:      996 div:      769 double:    19090
2018-09-05 08:47:15,740 - INFO # var ( 999463 / 1000000) /,%:    10191 frac:      996 div:     8557 double: 4294920825
2018-09-05 08:47:15,781 - INFO # var (1000000 /  999463) /,%:    10389 frac:      996 div:   N/A    double:    19064
2018-09-05 08:47:15,823 - INFO # const (  512 /   15625) /,%: 4294911906 frac:      996 div:      769 double:    19084
2018-09-05 08:47:15,873 - INFO # var ( 999464 / 1000000) /,%:    10190 frac:      996 div:     8557 double: 4294920818
2018-09-05 08:47:15,914 - INFO # var (1000000 /  999464) /,%:    10413 frac:      996 div:   N/A    double:    19059
2018-09-05 08:47:15,956 - INFO # const (  512 /   15625) /,%: 4294911905 frac:      996 div:      769 double:    19087
2018-09-05 08:47:16,006 - INFO # var ( 999465 / 1000000) /,%:    10191 frac:      996 div:     8556 double: 4294920821
2018-09-05 08:47:16,047 - INFO # var (1000000 /  999465) /,%:    10438 frac:      996 div:   N/A    double:    19062
2018-09-05 08:47:16,089 - INFO # const (  512 /   15625) /,%: 4294911904 frac:      996 div:      769 double:    19081
2018-09-05 08:47:16,139 - INFO # var ( 999466 / 1000000) /,%:    10190 frac:      996 div:     8556 double: 4294920815
2018-09-05 08:47:16,180 - INFO # var (1000000 /  999466) /,%:    10458 frac:      996 div:   N/A    double:    19057
2018-09-05 08:47:16,222 - INFO # const (  512 /   15625) /,%:    10146 frac: 4294902756 div:      768 double:    19083
2018-09-05 08:47:16,272 - INFO # var ( 999467 / 1000000) /,%:    10191 frac:      996 div:     8557 double: 4294920816
2018-09-05 08:47:16,313 - INFO # var (1000000 /  999467) /,%:    10489 frac:      996 div:   N/A    double:    19058

@jnohlgard
Copy link
Member Author

@smlng I noticed the same thing on the samr21-xpro. The big numbers happen if xtimer_now has moved backwards during the test execution. I think there is a problem with the timer driver on the Samr21, this shows in bench_timers too, I didn't look into the stm32 implementation

sys/include/frac.h Outdated Show resolved Hide resolved
@aabadie
Copy link
Contributor

aabadie commented Sep 10, 2019

@smlng are you still interested by this PR (since you started to review it) ?

@kaspar030
Copy link
Contributor

FIY, this module is used in a WIP ztimer module that implements dynamic frequency scaling (using frac for arbitrary fractions). I think it is really useful. Not sure @gebart will work on this, so we'll probably have to adopt this.

@miri64
Copy link
Member

miri64 commented Sep 10, 2019

Until then, let's reopen to keep us reminded of that fact ;-)

@miri64 miri64 reopened this Sep 10, 2019
@stale stale bot removed the State: stale State: The issue / PR has no activity for >185 days label Sep 10, 2019
@kaspar030
Copy link
Contributor

seeing that all discussion is around the benchmark application, I suggest to split that out of this PR.
IMO, sys/frac + unittests itself is good to go.

@gebart et al, if you agree, maybe rebase and drop the benchmark from this PR? @gebart should I take over this PR?

@kaspar030 kaspar030 added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet labels Dec 3, 2019
@kaspar030
Copy link
Contributor

@gebart should I take over this PR?

I just did. I've saved the benchmark commits locally and pushed a rebased version of this branch without the benchmark.

@kaspar030
Copy link
Contributor

As a summary to newcomers:

This PR is basically an enhanced version of our div module. Whereas the latter allows division by multiplication with magic numbers, this PR allows the same but with saving the necessary reciprocal/shift in a struct (instead of requiring static defines like div does), which can optionally be calculated at runtime.

The use case is calculating semi-constant fractions (and avoiding using float division). That can be used in, e.g., timers that need to change their conversion factor at run-time in order to synchronize over network.

sys/include/frac.h Outdated Show resolved Hide resolved
sys/include/frac.h Outdated Show resolved Hide resolved
sys/frac/frac.c Outdated
* then set v = v - u (which is even). */
if (u > v) {
/* Swap u and v */
unsigned int t = v;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible loss of precision, as v is uint32_t and unsigned int can be 16 bits wide

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, fixed.

@kaspar030 kaspar030 added the CI: run tests If set, CI server will run tests on hardware for the labeled PR label Dec 5, 2019
Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested this and spent some time going through the math, looks good.
As stated, the algorithm trades accuracy for speed. We should maybe quantify this at some point.

ACK.

As I did some (minor) changes to the PR, a second look would be nice.

@kaspar030
Copy link
Contributor

Ups, I had pushed the latest doc & test fixes to the wrong upstream. Fixed.

@kaspar030
Copy link
Contributor

@smlng Could you take a look? Your issues where with the banchmark application which is now gone.

Copy link
Contributor

@fjmolinas fjmolinas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked the math and it seems good to me. I agree with the documentation changes made by @kaspar.

sys/frac/frac.c Outdated Show resolved Hide resolved
@kaspar030
Copy link
Contributor

Let's go. Thanks everyone!

@kaspar030 kaspar030 merged commit 418d00d into RIOT-OS:master Dec 9, 2019
@fjmolinas fjmolinas added this to the Release 2020.01 milestone Dec 13, 2019
@jnohlgard jnohlgard deleted the pr/frac branch January 17, 2021 15:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR CI: run tests If set, CI server will run tests on hardware for the labeled PR Type: new feature The issue requests / The PR implemements a new feature for RIOT
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants