Brandon Simmons | 9 May 20:21 2014
Picon

Using mutable array after an unsafeFreezeArray, and GC details

A couple of updates: Edward Yang responded here, confirming the sort
of track I was thinking on:

  http://blog.ezyang.com/2014/05/ghc-and-mutable-arrays-a-dirty-little-secret/

And I can report that:
  1) cloning a frozen array doesn't provide the benefits of creating a
new array and freezing
  2) and anyway, I'm seeing some segfaults when cloning, freezing,
reading then writing in my library

I'd love to learn if there are any other approaches I might take, e.g.
maybe with my own CMM primop variants?

Thanks,
Brandon
Simon Marlow | 12 May 10:32 2014
Picon

Re: Using mutable array after an unsafeFreezeArray, and GC details

On 09/05/2014 19:21, Brandon Simmons wrote:
> A couple of updates: Edward Yang responded here, confirming the sort
> of track I was thinking on:
>
>    http://blog.ezyang.com/2014/05/ghc-and-mutable-arrays-a-dirty-little-secret/
>
> And I can report that:
>    1) cloning a frozen array doesn't provide the benefits of creating a
> new array and freezing
>    2) and anyway, I'm seeing some segfaults when cloning, freezing,
> reading then writing in my library
>
> I'd love to learn if there are any other approaches I might take, e.g.
> maybe with my own CMM primop variants?

I'm not sure exactly what your workload looks like, but if you have 
arrays that tend to be unmodified for long periods of time it's 
sometimes useful to keep them frozen but thaw before mutating.

How large are your arrays? Perhaps the new small array type (in HEAD but 
not 7.8) would help?

Cheers,
Simon
Brandon Simmons | 12 May 22:28 2014
Picon

Re: Using mutable array after an unsafeFreezeArray, and GC details

On Mon, May 12, 2014 at 4:32 AM, Simon Marlow <marlowsd <at> gmail.com> wrote:
> On 09/05/2014 19:21, Brandon Simmons wrote:
>>
>> A couple of updates: Edward Yang responded here, confirming the sort
>> of track I was thinking on:
>>
>>
>> http://blog.ezyang.com/2014/05/ghc-and-mutable-arrays-a-dirty-little-secret/
>>
>> And I can report that:
>>    1) cloning a frozen array doesn't provide the benefits of creating a
>> new array and freezing
>>    2) and anyway, I'm seeing some segfaults when cloning, freezing,
>> reading then writing in my library
>>
>> I'd love to learn if there are any other approaches I might take, e.g.
>> maybe with my own CMM primop variants?
>
>
> I'm not sure exactly what your workload looks like, but if you have arrays
> that tend to be unmodified for long periods of time it's sometimes useful to
> keep them frozen but thaw before mutating.

The idea is I'm using two atomic counters to coordinate concurrent
readers and writers along an "infinite array" (a linked list of array
segments that get allocated as needed and garbage collected as we go).
So currently each cell in each array is written to only once, with a
CAS.

>
(Continue reading)

Simon Marlow | 13 May 13:01 2014
Picon

Re: Using mutable array after an unsafeFreezeArray, and GC details

On 12/05/2014 21:28, Brandon Simmons wrote:
> The idea is I'm using two atomic counters to coordinate concurrent
> readers and writers along an "infinite array" (a linked list of array
> segments that get allocated as needed and garbage collected as we go).
> So currently each cell in each array is written to only once, with a
> CAS.

Certainly you should freeze arrays when you're done writing to them, 
this will help the GC a lot.

>> How large are your arrays? Perhaps the new small array type (in HEAD but not
>> 7.8) would help?
>
> Thanks, maybe so! The arrays can be any size, but probably not smaller
> than length 64 (this will be static, at compile-time).
>
> I read through https://ghc.haskell.org/trac/ghc/ticket/5925, and it
> seems like the idea is to improve array creation. I'm pretty happy
> with the speed of cloning an array (but maybe cloneSmallArray will be
> even faster still).
>
> It also looks like stg_casSmallArrayzh (in PrimOps.cmm) omits the card
> marking (maybe the idea is if the array is already at ~128 elements or
> less, then the card-marking is all just overhead?).

That right, the cards currently cover 128 elements, and there's also a 
per-array dirty bit, so the card table in an array smaller than 128 elts 
is just overhead.

Cheers,
(Continue reading)

S. Doaitse Swierstra | 13 May 20:20 2014
Picon

question about GADT's and error messages

Given the following code:

{-# LANGUAGE GADTs #-}
data Any a where
AInt :: Int -> Any Int

-- demo 1 does not compile
{-
demo1 a = do case a of
            (AInt i) -> print i

 Couldn't match expected type ‘t’ with actual type ‘IO ()’
   ‘t’ is untouchable
     inside the constraints (t1 ~ Int)
     bound by a pattern with constructor
                AInt :: Int -> Any Int,
              in a case alternative
     at /Users/doaitse/TryHaskell/TestGADT.hs:6:17-22
   ‘t’ is a rigid type variable bound by
       the inferred type of demo1 :: Any t1 -> t
       at /Users/doaitse/TryHaskell/TestGADT.hs:5:1
 Relevant bindings include
   demo1 :: Any t1 -> t
     (bound at /Users/doaitse/TryHaskell/TestGADT.hs:5:1)
 In the expression: print i
 In a case alternative: (AInt i) -> print i
Failed, modules loaded: none.
-}

-- all the following go through without complaints:
(Continue reading)

Daniel Wagner | 13 May 23:28 2014

Re: question about GADT's and error messages

I just hit a similar error the other day. I think the gist of it is that 
there are two perfectly good types, and neither is more general than the 
other. A slightly different example shows why more clearly:

foo (AInt i) = (3 :: Int)

Now, what type should this have?

foo :: Any a -> a
foo :: Any a -> Int

both seem pretty good, and neither is clearly better. It's not *as* 
obvious what the two candidates might be for your example, but maybe you 
could imagine something like these two types:

demo1 :: AInt a -> IO ()
type family Foo a
type instance Foo Int = IO ()
demo1 :: AInt a -> Foo a

Again, not too clear that one is better, I think.
~d

On 2014-05-13 14:20, S. Doaitse Swierstra wrote:
> Given the following code:
> 
> {-# LANGUAGE GADTs #-}
> data Any a where
> AInt :: Int -> Any Int
> 
(Continue reading)

Andres Löh | 13 May 23:51 2014

Re: question about GADT's and error messages

Hi.

Daniel is certainly right to point out general problems with GADT
pattern matching and principal types. Nevertheless, the changing
behaviour of GHC over time is currently a bit confusing to me.

In GHC-6.12.3, Doaitse's program fails with three errors (demo1,
demo2, demo4, all the GADT pattern matches without type signature),
and the error messages are:

/home/andres/trans/GT.hs:7:15:
    GADT pattern match in non-rigid context for `AInt'
      Probable solution: add a type signature for the scrutinee of the
case expression
    In the pattern: AInt i
    In a case alternative: (AInt i) -> print i
    In the expression: case a of { (AInt i) -> print i }

/home/andres/trans/GT.hs:33:18:
    GADT pattern match with non-rigid result type `t'
      Solution: add a type signature for the entire case expression
    In a case alternative: (AInt i) -> print i
    In the expression: case a of { (AInt i) -> print i }
    In the expression: do { case a of { (AInt i) -> print i } }

/home/andres/trans/GT.hs:41:18:
    GADT pattern match with non-rigid result type `t'
      Solution: add a type signature for the entire case expression
    In a case alternative: (AInt i) -> print i
    In the expression: case AInt 3 of { (AInt i) -> print i }
(Continue reading)

Richard Eisenberg | 14 May 20:32 2014

Re: question about GADT's and error messages

My understanding of OutsideIn leads me to believe that GHC 7.8 has the behavior closer to that spec. See
Section 5.2 of that paper
(http://research.microsoft.com/en-us/um/people/simonpj/Papers/constraints/jfp-outsidein.pdf),
which is a relatively accessible explanation of this phenomenon. Daniel's explanation is essentially a
condensed version of that section.

I'm not surprised that the behavior changed between GHC 6.x and 7.x, as I believe 7.x is what brought in
OutsideIn. I don't know much about the change between 7.6 and 7.8, though. And, I agree that the
"untouchable" error messages are generally inscrutable. When I see that message in my own code, my
takeaway is generally "I have a mistake somewhere near that line", nothing more specific or useful. I've
accordingly posted a bug report #9109 (https://ghc.haskell.org/trac/ghc/ticket/9109). Please
comment there if you have either useful examples or other contributions to the fix -- it may be hard to get
this one right.

Richard

On May 13, 2014, at 5:51 PM, Andres Löh <andres <at> well-typed.com> wrote:

> Hi.
> 
> Daniel is certainly right to point out general problems with GADT
> pattern matching and principal types. Nevertheless, the changing
> behaviour of GHC over time is currently a bit confusing to me.
> 
> In GHC-6.12.3, Doaitse's program fails with three errors (demo1,
> demo2, demo4, all the GADT pattern matches without type signature),
> and the error messages are:
> 
> /home/andres/trans/GT.hs:7:15:
>    GADT pattern match in non-rigid context for `AInt'
(Continue reading)


Gmane