wren ng thornton | 6 Dec 2011 18:48

Revert a CAF?

So, I have an optimization/internals question. Does the GHC API have any 
hooks for being able to revert a CAF to the original expression, thus 
discarding the previously computed result?

The reason I'm wanting this is that I have a particular CAF which is an 
infinite list. Unfolding that list takes a fair deal of work, so we want 
to share it whenever possible; however it doesn't take an overwhelming 
amount of work, so if we know we've evaluated more of the list than 
necessary (for a long while), it'd be nice to be able to revert the 
evaluation in order to save on memory overhead (e.g., by calling relax 
:: IO()).

I could hack something together based on unsafePerformIO and top-level 
IORefs, and it's clear that this is in fact a safe thing to do, but I'm 
worried about the semantic issues inherent in unsafePerformIOed 
top-level IORefs (e.g., the fact that their scope isn't particularly 
well defined: is it per library instance? per runtime?...). 
Unfortunately, for what I'm doing, it isn't really feasible to just 
leave the IO type in there nor to pass around the infinite list so we 
can use scoping rules to decide when to free it.

(Feel free to offer alternative suggestions to handling this situation too.)

--

-- 
Live well,
~wren
Dan Doel | 6 Dec 2011 19:59
Picon
Gravatar

More liberal than liberal type synonyms

Greetings,

In the process of working on a Haskell-alike language recently, Ed
Kmett and I realized that we had (without really thinking about it)
implemented type synonyms that are a bit more liberal than GHC's. With
LiberalTypeSynonyms enabled, GHC allows:

    type Foo a b = b -> a
    type Bar f = f String Int

    baz :: Bar Foo
    baz = show

because Bar expands to saturate Foo. However, we had also implemented
the following, which fails in GHC:

    type Foo a b = b -> a
    type Bar f = f (Foo Int) (Foo Int)
    type Baz f g = f Int -> g Int

    quux :: Bar Baz
    quux = id

That is: type synonyms are allowed to be partially applied within
other type synonyms, as long as similar transitive saturation
guarantees are met during their use.

I don't know how useful it is, but I was curious if anyone can see
anything wrong with allowing this (it seems okay to me after a little
thought), and thought I'd float the idea out to the GHC developers, in
(Continue reading)

Simon Peyton-Jones | 6 Dec 2011 23:09
Picon
Favicon
Gravatar

RE: Revert a CAF?

GHCi does this somehow, so it's definitely possible; Simon M will know.

|  -----Original Message-----
|  From: glasgow-haskell-users-bounces <at> haskell.org [mailto:glasgow-haskell-users-
|  bounces <at> haskell.org] On Behalf Of wren ng thornton
|  Sent: 06 December 2011 17:49
|  To: GHC-users List
|  Subject: Revert a CAF?
|  
|  So, I have an optimization/internals question. Does the GHC API have any
|  hooks for being able to revert a CAF to the original expression, thus
|  discarding the previously computed result?
|  
|  The reason I'm wanting this is that I have a particular CAF which is an
|  infinite list. Unfolding that list takes a fair deal of work, so we want
|  to share it whenever possible; however it doesn't take an overwhelming
|  amount of work, so if we know we've evaluated more of the list than
|  necessary (for a long while), it'd be nice to be able to revert the
|  evaluation in order to save on memory overhead (e.g., by calling relax
|  :: IO()).
|  
|  I could hack something together based on unsafePerformIO and top-level
|  IORefs, and it's clear that this is in fact a safe thing to do, but I'm
|  worried about the semantic issues inherent in unsafePerformIOed
|  top-level IORefs (e.g., the fact that their scope isn't particularly
|  well defined: is it per library instance? per runtime?...).
|  Unfortunately, for what I'm doing, it isn't really feasible to just
|  leave the IO type in there nor to pass around the infinite list so we
|  can use scoping rules to decide when to free it.
|  
(Continue reading)

John Meacham | 6 Dec 2011 23:14
Favicon

Re: Revert a CAF?

Can you use a weak pointer to do what you want?
If you keep a weak pointer to the head of your expensive list then
itwill be reclaimed at the next major GC I believe. I have used
weakpointers for vaugely similar purposes before.
I guess a downside is that they will always be reclaimed on GC even
ifthere isn't memory pressure, I think.

   John
(resent, accidentally sent to wrong address first)
Simon Marlow | 7 Dec 2011 11:03
Picon

Re: Revert a CAF?

On 06/12/2011 17:48, wren ng thornton wrote:
> So, I have an optimization/internals question. Does the GHC API have any
> hooks for being able to revert a CAF to the original expression, thus
> discarding the previously computed result?
>
> The reason I'm wanting this is that I have a particular CAF which is an
> infinite list. Unfolding that list takes a fair deal of work, so we want
> to share it whenever possible; however it doesn't take an overwhelming
> amount of work, so if we know we've evaluated more of the list than
> necessary (for a long while), it'd be nice to be able to revert the
> evaluation in order to save on memory overhead (e.g., by calling relax
> :: IO()).
>
> I could hack something together based on unsafePerformIO and top-level
> IORefs, and it's clear that this is in fact a safe thing to do, but I'm
> worried about the semantic issues inherent in unsafePerformIOed
> top-level IORefs (e.g., the fact that their scope isn't particularly
> well defined: is it per library instance? per runtime?...).
> Unfortunately, for what I'm doing, it isn't really feasible to just
> leave the IO type in there nor to pass around the infinite list so we
> can use scoping rules to decide when to free it.
>
> (Feel free to offer alternative suggestions to handling this situation
> too.)

It would be possible, but it's not quite as straightforward as you might 
think.  Suppose you have a program like this:

xs = [1..100000]
evens = filter ((==0) . (`mod` 2)) xs
(Continue reading)

Twan van Laarhoven | 7 Dec 2011 16:16
Picon
Gravatar

Re: Revert a CAF?

On 06/12/11 18:48, wren ng thornton wrote:
> So, I have an optimization/internals question. Does the GHC API have any
> hooks for being able to revert a CAF to the original expression, thus
> discarding the previously computed result?
>
> ...
>
> I could hack something together based on unsafePerformIO and top-level
> IORefs, and it's clear that this is in fact a safe thing to do, but I'm
> worried about the semantic issues inherent in unsafePerformIOed
> top-level IORefs (e.g., the fact that their scope isn't particularly
> well defined: is it per library instance? per runtime?...).
> Unfortunately, for what I'm doing, it isn't really feasible to just
> leave the IO type in there nor to pass around the infinite list so we
> can use scoping rules to decide when to free it.

How bad is the IORef solution really? I.e. can someone more well versed 
in ghc internals tell me why this wouldn't work?

     type CAF a = IORef (() -> a, a)
     mkCAF :: (() -> a) -> a
     mkCAF f = unsafePerformIO $ newIORef (f, f ())
     getCAF :: CAF a -> a
     getCAF = snd . unsafeDupablePerformIO . readIORef
     resetCAF :: CAF a -> IO ()
     resetCAF = modifyIORef $ \(f,_) -> (f, f ())

     myCAF :: CAF [Int]
     myCAF = mkCAF $ \_ -> [1..1000000]
     {-# NOINLINE myCAF #-}
(Continue reading)

Bas van Dijk | 7 Dec 2011 16:45
Picon
Gravatar

GHC HEAD build error

Hello,

I'm trying to build GHC HEAD but get the following error:

"inplace/bin/ghc-stage1"   -H64m -O0 -fasm -Iincludes -Irts
-Irts/dist/build -DCOMPILING_RTS -package-name rts  -dcmm-lint      -i
-irts -irts/dist/build -irts/dist/build/autogen -Irts/dist/build
-Irts/dist/build/autogen            -optc-O2   -c
rts/HeapStackCheck.cmm -o rts/dist/build/HeapStackCheck.o

rts/HeapStackCheck.cmm:159:305: parse error on input `('

The bug is in the GC_GENERIC macro on line 99:

Capability_interrupt(MyCapability())      != 0 :: CInt

However, I can't spot the problem.

Bas
Ian Lynagh | 7 Dec 2011 16:54
Picon
Gravatar

Re: GHC HEAD build error

On Wed, Dec 07, 2011 at 04:45:31PM +0100, Bas van Dijk wrote:
> 
> "inplace/bin/ghc-stage1"   -H64m -O0 -fasm -Iincludes -Irts
> -Irts/dist/build -DCOMPILING_RTS -package-name rts  -dcmm-lint      -i
> -irts -irts/dist/build -irts/dist/build/autogen -Irts/dist/build
> -Irts/dist/build/autogen            -optc-O2   -c
> rts/HeapStackCheck.cmm -o rts/dist/build/HeapStackCheck.o
> 
> rts/HeapStackCheck.cmm:159:305: parse error on input `('

This is probably caused by old header files in includes/. Updating to
the latest HEAD and making clean should fix it.

Thanks
Ian
Daniel Fischer | 7 Dec 2011 17:02

Re: GHC HEAD build error

On Wednesday 07 December 2011, 16:45:31, Bas van Dijk wrote:
> Hello,
> 
> I'm trying to build GHC HEAD but get the following error:
> 
> "inplace/bin/ghc-stage1"   -H64m -O0 -fasm -Iincludes -Irts
> -Irts/dist/build -DCOMPILING_RTS -package-name rts  -dcmm-lint      -i
> -irts -irts/dist/build -irts/dist/build/autogen -Irts/dist/build
> -Irts/dist/build/autogen            -optc-O2   -c
> rts/HeapStackCheck.cmm -o rts/dist/build/HeapStackCheck.o
> 
> rts/HeapStackCheck.cmm:159:305: parse error on input `('
> 
> The bug is in the GC_GENERIC macro on line 99:
> 
> Capability_interrupt(MyCapability())      != 0 :: CInt
> 
> However, I can't spot the problem.

I had the same recently, it's probably because GHCConstants.h and 
DerivedConstants.h have been moved but you still have them in include/ from 
a previous build.
Deleting them should fix it.
Dan Doel | 7 Dec 2011 17:19
Picon
Gravatar

Re: [Haskell-cafe] More liberal than liberal type synonyms

On Wed, Dec 7, 2011 at 5:48 AM, Dmitry Kulagin <dmitry.kulagin <at> gmail.com> wrote:
> I am still pretty new in Haskell, but this problem annoys me already.
>
> If I define certain monad as a type synonym:
>
>    type StateA a = StateT SomeState SomeMonad a
>
> Then I can't declare new monad based on the synonym:
>
>    type StateB a = StateT SomeOtherState StateA a
>
> The only way I know to overcome is to declare StateA without `a':
>
>    type StateA = StateT SomeState SomeMonad
>
> But it is not always possible with existing code base.

I'm afraid my proposal doesn't make this work. You could perhaps
define StateB, but when you expand in a type you get:

    StateB a = StateT SomeOtherState StateA a

which has a partially applied StateA, and is rejected. The only way to
make this work is to eta reduce StateA manually, or make GHC recognize
when a synonym can be eta reduced in this way (which might be both
possible and useful as a separate proposal).

My extension fell within the liberal type synonym space, which says
that if you have:

(Continue reading)


Gmane