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

examples: add gcd #935

Merged
merged 2 commits into from
May 31, 2024
Merged

examples: add gcd #935

merged 2 commits into from
May 31, 2024

Conversation

proppy
Copy link
Member

@proppy proppy commented Apr 20, 2023

@proppy
Copy link
Member Author

proppy commented Apr 20, 2023

rebased

@proppy
Copy link
Member Author

proppy commented Apr 20, 2023

/cc @mdagois

// https://en.wikipedia.org/wiki/Greatest_common_divisor#Euclidean_algorithm
fn gcd_euclidean<N: u32, DN: u32 = {N * u32:2}>(a: uN[N], b: uN[N]) -> uN[N] {
let (_, gcd) = for (i, (a, b)) in range(u32:0, DN) {
let (d, r) = std::iterative_binary_div(a, b);
Copy link
Member Author

Choose a reason for hiding this comment

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

should move this in the else case, so that we don't perform unnecessary division when the remainder is 0.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure I understand. How can this move into the else case if the result of the computation is the condition?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think gcd is a good candidate for proc implementations, which would let you do the "early return" I think you're describing. Each proc tick would do one division (or gcd_binary_match), and you send the output when you reach the stop condition.

Fine to leave as a TODO, and these function implementations are nice because they work well w/ quickcheck.

Copy link
Member Author

Choose a reason for hiding this comment

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

Not sure I understand. How can this move into the else case if the result of the computation is the condition?

@meheff since we always pass r to the next iteration, I was thinking we could sel based on the result of the previous division, rather than always performing the same division again and again until the end of the loop.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think gcd is a good candidate for proc implementations, which would let you do the "early return" I think you're describing.

It could be interesting to compare a proc implementation to the automatically pipelined version.

Copy link
Member Author

Choose a reason for hiding this comment

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

@meheff since we always pass r to the next iteration, I was thinking we could sel based on the result of the previous division, rather than always performing the same division again and again until the end of the loop.

As discussed simplified the implementation to only trigger div_mod in for recurrence w/ a non-zero modulo.

This apparently result in a reduced critical path and bom, see https://colab.research.google.com/gist/proppy/01142e33a2be8b71d6b317ee4ce7fde4/xls-playground-sandbox.ipynb

Copy link
Collaborator

@grebe grebe left a comment

Choose a reason for hiding this comment

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

This is great!

xls/dslx/stdlib/std.x Outdated Show resolved Hide resolved
xls/dslx/stdlib/std.x Outdated Show resolved Hide resolved
xls/dslx/stdlib/std.x Outdated Show resolved Hide resolved
xls/dslx/stdlib/std.x Outdated Show resolved Hide resolved
// https://en.wikipedia.org/wiki/Greatest_common_divisor#Euclidean_algorithm
fn gcd_euclidean<N: u32, DN: u32 = {N * u32:2}>(a: uN[N], b: uN[N]) -> uN[N] {
let (_, gcd) = for (i, (a, b)) in range(u32:0, DN) {
let (d, r) = std::iterative_binary_div(a, b);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think gcd is a good candidate for proc implementations, which would let you do the "early return" I think you're describing. Each proc tick would do one division (or gcd_binary_match), and you send the output when you reach the stop condition.

Fine to leave as a TODO, and these function implementations are nice because they work well w/ quickcheck.

@cdleary cdleary added the app Application level functionality (examples, uses of XLS stack) label Mar 27, 2024
@proppy
Copy link
Member Author

proppy commented May 31, 2024

I think gcd is a good candidate for proc implementations

Filed #1444

@proppy
Copy link
Member Author

proppy commented May 31, 2024

PTAL

@copybara-service copybara-service bot merged commit d2da104 into google:main May 31, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
app Application level functionality (examples, uses of XLS stack) Reviewing Internally
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants