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

Improve projection detection to make Vector indexing O(1) #110

Open
ollef opened this issue Jun 14, 2018 · 2 comments
Open

Improve projection detection to make Vector indexing O(1) #110

ollef opened this issue Jun 14, 2018 · 2 comments

Comments

@ollef
Copy link
Owner

ollef commented Jun 14, 2018

This was originally discovered in #104, and there's also a workaround there.

The ReturnDirection pass detects when it's safe for a function that returns something of unknown type to return it by (derived) pointer instead of by copying to an out parameter. For some reason this doesn't kick in for vector indexing. My hunch is that this is causing us to generate code that LLVM's optimiser doesn't easily see through, meaning that we don't get the constant-time goodness we would want.

This needs to be investigated and fixed if possible.

@bglgwyng
Copy link

Have you considred Vector indexed by Bin n rather than Nat?
Here's a (surely invalid) sixten code for it.

-- Bin n represents n bits.
-- I (O (I H)) = 101(2)
type Bin: Nat -> Type where
  H: Bin 0
  I: Bin n -> Bin (Sunn c)
  O: Bin n -> Bin (Sunn c)

shift: n -> Bin m -> Bin (n + m)
shift Zero x = x
shift (Succ n) H = O (shift n H)
shift (Succ n) (I x) = I (shift n x)
shift (Succ n) (O x) = O (shift n x)


Vector : forall n. Bin n -> Type -> Type
Vector (H) _ = Unit
Vector (I H) a = a
Vector @n (I x) a = Pair (Pair (Vector y a) (Vector y a)) (Vector x a)
  where y = I (shift I (n - 1))
Vector (O x) a = Vector x a)


index : forall a. forall n. (len : Bin n) -> Vector len a -> Bin n -> Maybe a
index H MkUnit _ = Nothing
index (I H) x 0 = Just x
index (I y) (MkPair x _) (I z) = index y x z
index (I y) (MkPair _ x) (O z) = index y x z
index (O y) x (O z) = index y x z

With this definition, Vector n a is built like a binary trie and an index can be considered to be a path of trie .
I think this definition represents the machine behavior more precisely. Random access is not O(1) but O(log n) where n is the length of address. Roughly speaking, memory access in 64bit address is 2 time slower than in 32 bit one.

I'm not sure LLVM can generate the optimized binary from this definition.
But I think this definition gives sufficient information to do so.
Because the pattern maching process within index skips elements in MkPairs whose summation of size is equal to given index i.

@ollef
Copy link
Owner Author

ollef commented Jun 27, 2020

I haven't tried that, but it sounds like a fun idea to try!

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

No branches or pull requests

2 participants