-
Notifications
You must be signed in to change notification settings - Fork 43
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
Indexed update #55
base: master
Are you sure you want to change the base?
Indexed update #55
Conversation
Sorry I didn't realize this in our earlier discussion, but I think your |
I doubt it would be a good idea to make Vector an instance of IxConstructible with just Normally a Constructible has cons and snoc for prepending/appending stuff via semigroup - but in the case of Vectors
so a monoidal operation on that element.. which differs from overwriting the contents of that element.. Just using
which follows from the semigroup and cancellative-property of vectors. I think |
The version in the ghc-8 branch has different laws for Sorry this is a super brief description of the motivation, but I don't have time for more detail right now. |
That may be the case for maps, but i currently just talk about Vectors (using a single unboxed malloced blob of memory). let z = zero :: UVector 3 Double -- == fromList [0,0,0]
consAt 0 5 z -- fromList [5,0,0]
snocAt 0 5 z -- fromList [5,0,0]
z & 0 !~ 5 -- fromList [5,0,0]
-- but
consAt 0 5 (consAt 0 (-5) z) -- fromList [0,0,0] - as expected that the fooAt just carries the monoid-operation through to the given element
(z & 0 !~ 5) & 0 !~ (-5) -- fromList [-5,0,0] - with a "setter" there is no "way back" on that operation as only the last action is commited; also no monoid constraint on the "values" is needed; i.e. vector does not have to be a monoid by itself - though it should. So in short i understand that you can recover the behaviour of my proposed At least for Vectors as "fixed amount of random-access-memory" that would be a reasonable (and fast!) imlpementation. |
Got it. I understand the distinction now, and I agree that something like Three more things to consider before merging:
Thanks again for going through this work! |
Regarding the bulk-update i think it depends on how GHC generates Core for that use-case. I have not enough knowledge about the internals and will read up on there generated core to answer the issue. At the moment you can implement (//) idxs vals vec = vec & foldl1 (.) $ zipWith (!~) idxs vals but that would depend on GHC fusing the composed function to a single in-memory-update with just 1 copying of the vector (in case you hold a reference to the old). ATM
and i THINK GHC can manage to optimize the allocation & duplication away if you hold no reference to the old vector after that point in your program. If this is the case than you can implement I will write a specialized vec & (5 !~ 23) . (7 !~ 42)
-- opposed to
vec // [5,7] [23,42]
-- or
vec // [(5,23),(7,42)] because it feels "more functional" and even allows for mixing "setting" with "modifying" (as setting is just a modify with "const val"): vec & (5 !~ 23) . (7 !~ 42) . (0 %~ (+2)) Long story short: I will implement an optimized Regarding GHC8.0: The change will be in master as well as the ghc8.0-branch as these commits (and the follwoing will) flawlessly merge with both :) |
I'd be very pleasantly surprised if GHC can do that automatically. I was imagining that
into
|
Solving that problem in a generic way gave me headaches for a week and i still have not solved it completely. Basically with (monadic) Stream Fusion and Recycling you can implement Roman Leshchinskiy did great work in that field and i base my thing on "Recycle your Arrays" (http://dl.acm.org/citation.cfm?id=1506073 - depending on the jurisdiction of the country you live in you can enter the doi on sci-hub.cc to get it). But he did not abstract. He just implemented it for his "vector v a"-datatype with a fixed structure. I tried to abstract that into typeclasses, but i face challenges convincing the type-checker that those optimizations are generally valid. My current dev-branch is https://github.com/Drezil/subhask/blob/ghc8.0-indexed_update/src/SubHask/Algebra/Vector/RMStreams.hs#L142-L151 (with the missing rules highlighted). I also included a test-case in https://github.com/Drezil/subhask/blob/ghc8.0-indexed_update/examples/ghc-test-linear-algebra.lhs which currently does nothing. I instantiated the classes for UVector, but i have not changed the update-rules to use the new recycling-method yet. After i had time for that i want to make sure that the rules actually fire (-ddump-rule-firings). But thats just for the current heads-up. |
I don't know if i understood the GHC-Internals right .. but i suppose you are to make a copy when you change a structure because of sharing and the GHC replaces it with an inline-replacement if you hold no pointers to the old structure afterwards, correct?
Otherwise this is just a plain malloc/memcpy of the vector with an update to the specific position.
Compiles and seems to work for me, but i havent run the test-suite yet.