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

add simd example #13

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

add simd example #13

wants to merge 2 commits into from

Conversation

attacker0211
Copy link
Collaborator

@attacker0211 attacker0211 commented Jun 14, 2022

Implements #11

Copy link

@penzn penzn left a comment

Choose a reason for hiding this comment

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

Sorry, came across by accident.

Looks like SIMD mul technically processes one element, usually for matrices it is easier to write a vector dot product and then build the rest on top of it.

Additionally, floating point arithmetic is more interesting, as floating operations are more expensive.

fn mul(a: u64, b: u64) -> u64 {
let va: v128 = u64x2_splat(a);
let vb: v128 = u64x2_splat(b);
let c = u64x2_extract_lane::<1>(i64x2_mul(va, vb));
Copy link

Choose a reason for hiding this comment

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

I think this is technically a scalar multiplication - it fills all lanes with the same value and then extracts just one value out of the result.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thank you so much for your review. I wasn't familiar with simd and made a mistake. Would appreciate feedbacks on the new code.

Comment on lines 15 to 22
fn dot(a: Vec<u64>, b: Vec<u64>) -> u64 {
assert!(a.len() == b.len());
let mut sum: u64 = 0;
for i in 0..a.len() {
sum += Self::mul(a[i], b[i]);
}
sum
}
Copy link

Choose a reason for hiding this comment

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

Dot product is the smallest unit of work in matrix multiplication that can be implemented in SIMD, it usually works by taking N worth of elements from the first array and second array, multiplying them via SIMD, then adding N results to the intermediate vector sum (N is number of lanes). Intermediate sum is the added up at the end, also for input sizes not divisible by N the remainder needs to be calculated manually.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Updated. Please let me know if anything I could do better. I assume floating point implementation should be similar (please let me know if it isn't) so I will update floating point examples once this is ok :)

Comment on lines +1 to +4
u64x2-scalar-mul: func(a: u64, b: list<u64>) -> list<u64>
u64x2-dot: func(a: list<u64>, b: list<u64>) -> u64
u64x2-inner: func(a: list<u64>, b: list<u64>) -> list<u64>
u64x2-mat-mul: func(a: list<list<u64>>, b: list<list<u64>>) -> list<list<u64>>
Copy link
Contributor

Choose a reason for hiding this comment

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

rather than using list you should use singlestore compatible packed 64 bit vectors:

https://docs.singlestore.com/db/v7.8/en/reference/sql-reference/vector-functions/vector-functions.html

use core::arch::wasm32::*;

impl simd::Simd for Simd {
fn u64x2_scalar_mul(a: u64, b: Vec<u64>) -> Vec<u64> {
Copy link
Contributor

Choose a reason for hiding this comment

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

please add docstrings to each function explaining it's purpose

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants