Hi Brad,

Brad Chamberlain wrote:
>
> Hi Greg --
>
>> 1. It would be nice to see the default value of config
>>    constants in the help message (in the table that lists
>>    the command-line options).
>
> I completely agree.  We actually used to support this, but ended up
> retiring it at some point when the implementation path taken became
> unwieldy, with the best of intentions to put it back in, but then never
> have.  A question for you is whether you'd prefer to see the logical
> (source) value of the config or the actual (execution time) value.
> For example, given:
>
>      config var m = 10,
>                 n = m;
>
> would you prefer ./a.out --help to say:
>
>      m = 10
>      n = m
>
> or:
>
>      m = 10
>      n = 10

The second is fine.  It's mostly so the user can see what value a
variable would have if it's not provided on the command line.

>
> * the ability to support short-form options for a given config (e.g., make
>    -o foo.txt equivalent to --outputfile foo.txt).

That would be nice!

>
>
>> 2. We've found it necessary often enough to iterate over
>>    the ranges of a domain separately.  Doing array.domain.dim(1)
>>    is a bit of typing.  Would it be possible to have a
>>    method array.range(i)?
>
> We could potentially add this -- it seems like there's always a tension
> between providing a minimal set of features for clarity/precision (an
> array doens't technically have ranges, its domain does -- and then only
> if its a rectangular array) and a convenient set of features.  In this
> case we've currently opted for minimalism, but I could personally go
> either way on it.
>
> Note that with a slight bit of bother (relying on a non-public symbol
> name), you could provide such a shortcut yourself by supplying this method:
>
>      proc _array.dim(d) {
>        return this.domain.dim(d);
>      }
>
> which would let you do:
>
>      ...A.dim(1)...
>      ...A.dim(2)...
>
> The fragile aspect of this is that the identifier '_array' isn't public
> and is subject to change...
>
> Other options (short of us changing the internal modules) might be to
> create a helper iterator that takes care of these details for you or to
> name the array's domain and use that instead (whether or not these make
> sense depend a lot on the context of course).

We started to save the ranges separately with the image data structure
    class clrimage {
      var nrow, ncol, npix : int;       /* size of image */
      var rows : range;                 /* all the rows */
      var cols : range;                 /* all the columns */
      var area : domain(rank=2);        /* the image plane */
      var c1 : [area] real;             /* first color plane */
      /* etc. */
    }
and then setting up the ranges and domain in the constructor.

>
>> 4. What is the reason for not setting a class instance to nil
>>    after calling delete, if you can't use it any more?
>
> This has been discussed at times, and I believe we could.  But note that
> it wouldn't necessarily make your code safe.  Specifically, if you did
> something like:
>
>      var myC = new C();
>      var myC2 = myC;    // alias myC
>      delete myC;        // assume this sets myC = nil
>      myC2.foo();
>
> in the current implementation, 'myC2' would still point to the
> just-freed object, and so would not be 'nil'.  In order to make things
> more bulletproof, one would need to make all class objects use a handle
> or double-dereference.  We've discussed supporting a "safety over
> performance" compilation mode that would take this approach for all
> class variables to help catch errors, but then it's never felt high
> enough priority for anyone to undertake.
>
> Doing the 'nil upon delete' that you suggest would help with some cases,
> but not others, and so may be worthwhile, but I think we haven't dived
> into it because it feels like such a partial solution.
>

This is coming more from our C programming style.  Allocation
routines for images can be called even if there's already one
stored in a pointer - the routine checks if non-NULL and frees
an existing image before allocating a new one.  So the free
routine has to set the pointer to NULL when done.  In Chapel we do
an extern class to interface to this data structure, but since
the pointer isn't set to nil after a delete (even though the free
routine is called in the class' destructor), if we try to re-use
the variable we get a segfault.

Or, in Chapel you can call delete on a nil class variable and it
will do nothing.  If delete did set the instance to nil then it
would be safe to call delete again on the variable.  Now, though,
it causes a crash.
     class C { var a : int }
     var c = new C();
     delete c;
     delete c;
     > Segmentation fault

>
>> 5. The compiler stops after each error, which makes it
>>    frustrating to fix problems since it's not the fastest.
>>    It feels like trying to get a script working: you hit
>>    one typo then have to re-start the script.
>
> Yeah, this is something we'd like to improve, and others have commented
> on it as well.  Some errors are easy to plow through to see the next
> one; others are harder (e.g., if I can't resolve the type of a variable,
> I'm going to have trouble doing much with code that's downstream of
> it).  Is there a particular class of errors that you're running into
> that is giving you these problems?
>

No, generally all over, unfortunately.

>
>> 6. The minloc and maxloc reductions need a zipper with the
>>    array and its domain.  Can't it get the domain from the
>>    array itself?  'maxloc reduce zip(A, A.domain)' is just
>>    verbose, although having the ability to provide a
>>    separate labeling sequence from the data would be useful
>>    in other situations.
>
> I agree that this is frustrating in the common case.  The challenge here
> is that the compiler doesn't have any special knowledge of minloc and
> maxloc compared to any other reduction that an end-user might write.  So
> for example, when you type:
>
>      myReduction reduce expr
>
> this gets translated into a loop over 'expr', passing its elements into
> the methods of 'myReduction' for accumulation and combining.  For
> example, if I write:
>
>      myReduction reduce A
>
> you can think of this as being rewritten as something like:
>
>      forall a in A do
>        myReduction.accumulate(a);
>
> and the problem is that, given an element from an array ('a' in this
> example, or more specfically, perhaps the value 1.2 if it were an array
> of reals), there's no way to get back to its index in the collection if
> it's not passed down directly.  So the zippered iteration effectively
> gives us the ability to do:
>
>      forall (a,i) in zip(A, A.domain) do
>        myReduction.accumulate(a, i);
>
> The other reason for the current approach is that you may be reducing
> something that is not an array and therefore does not have obvious
> logical indices for it -- so the explicit zippering allows you to
> specify some numbering scheme for such cases.
>
> Of course for the array case, you can create a helper minloc routine:
>
>      proc minloc(A) {
>        return minloc reduce (A, A.domain);
>      }
>
> which would save you both the duplication and typing the 'reduce' keyword.

I didn't know if the reduce could be overloaded for an array
argument, even if internally it was combined in a zipper or
instead of the forall over A generated
    forall ind in A.domain do
      myReduction.accumulate(A(ind), ind);
This would be in addition to the current syntax.

>
> -Brad
>

------------------------------------------------------------------------------
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users

Reply via email to