What are the key differences between the Repa 2 and 3 APIs?

泪湿孤枕 提交于 2019-11-30 07:01:37

The new representation type parameters don't automagically force when needed (it's probably a hard problem to do that well) - you still have to force manually. In Repa 3 this is done with the computeP function:

computeP
  :: (Monad m, Repr r2 e, Fill r1 r2 sh e)
  => Array r1 sh e -> m (Array r2 sh e)

I personally really don't understand why it's monadic, because you can just as well use Monad Identity:

import Control.Monad.Identity (runIdentity)
force
  :: (Repr r2 e, Fill r1 r2 sh e)
  => Array r1 sh e -> Array r2 sh e
force = runIdentity . computeP

So, now your output function can be rewritten with appropriate forcing:

output img = map cast . f . blur . f . blur . f . blur . f $ grey
  where ...

with an abbreviation f using a helper function u to aid type inference:

u :: Array U sh e -> Array U sh e
u = id
f = u . force

With these changes, the speedup is quite dramatic - which is to be expected, as without intermediate forcing each output pixel ends up evaluating much more than is necessary (the intermediate values aren't shared).

Your original code:

real    0m25.339s
user    1m35.354s
sys     0m1.760s

With forcing:

real    0m0.130s
user    0m0.320s
sys     0m0.028s

Tested with a 600x400 png, the output files were identical.

computeP is the new force.

In Repa 3 you need to use computeP everywhere you would have used force in Repa 2.

The Laplace example from repa-examples is similar to what you're doing. You should also use cmap instead of plain map in your blur function. There will be a paper explaining why on my homepage early next week.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!