Hi, Dave,

You are accessing the method size() of the *field* a_prefix_sum
of the current object (i.e., "this").  However, the message says
that the *target* of the method *must be local* to the place you
are running in.  It then says what it thinks that place is, and
what it knows about the place where the method target lives.

So, the message says:

> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/PrefixSum.x10:42:
> Place type error: either method target should be local or 
> method should be global. 
>          Method target: PrefixSum.this.a_prefix_sum 
>          Method target place: null 
>          Current place: PrefixSum#this.home 
>          Method: size

The target is "this.a_prefix_sum", and the home place of that
object is "null" (which is to say "unknown" -- we ought to improve
our error messages).  The compiler knows that since you are
within a non-global instance method of class PrefixSum, you must
be running in the place where the current instance lives, namely
"PrefixSum#this.home".

You need to tell the compiler that the field a_prefix_sum lives
in the same place as the enclosing object.  The simplest way to
do this is to change the declaration of the field to say:

   val a_prefix_sum:  Array[Int](1)!;

or, in a more expanded form

   val a_prefix_sum:  Array[Int](1){self.home==this.home};

This says that the home place of the object the field refers to
(self.home) must be the same as the home place of the object that
contains the field (this.home).  The compiler will statically
verify that fact.  Since you always initialize that field with a
new object created in the constructor, the compiler knows that
it must have been created at the place where the enclosing object
is being constructed, so you don't have to change anything else
in the code.

Incidentally, this is a classic example of an underspecified type:
the type you specify is a supertype of the type you actually need.

However, while the type is underspecified, it is essentially
harmless, because the parts of the program we discussed so far do
access the object in the correct place, even if the static type
information does not reflect that.  Your original issue is
different.

You are invoking place_str() in a place that is not the home place
of the enclosing object, and thus the dynamic check (which the
compiler inserted for you) fails.  When compiling with
-STATIC_CALLS, you will get a (legitimate) static error at that
point.

If you intend to call a method from a place that is not the home
place of the object, you need to mark it "global".  You also need
to ensure that all the data it accesses is either also marked
"global", or retrieved via an "at (this)" (same as "at (this.home)").
In your particular case, the method place_str() should be global,
as should the field a_prefix_sum.

Note that you may have more errors of this kind in the parts of
the program that you have not posted to the list.  Please address
them accordingly.

The rule of thumb is that once you start writing multi-place code,
you should stop relying on the compiler to insert the dynamic
checks for you, but instead bite the bullet, build with -STATIC_CALLS,
and fix the errors.

Hope this helps,
        Igor

Dave Hudak <dhu...@osc.edu> wrote on 07/30/2010 09:10:49 AM:

> Hi Igor (and all),
> 
> Here is the output from the compiler:
> 
> dhu...@oscnet166 125%> x10c++ -STATIC_CALLS -o Driver Driver.x10 
> PrefixSum.x10 AsyncPrefixSum.x10 DistPrefixSum.x10
> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/AsyncPrefixSum.
> x10:48: Place type error: either method target should be local or 
> method should be global. 
>          Method target: AsyncPrefixSum.this.a_prefix_sum 
>          Method target place: null 
>          Current place: AsyncPrefixSum#this.home 
>          Method: size
> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/AsyncPrefixSum.
> x10:49: Place type error: either method target should be local or 
> method should be global. 
>          Method target: AsyncPrefixSum.this.a_prefix_sum 
>          Method target place: null 
>          Current place: AsyncPrefixSum#this.home 
>          Method: size
> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/PrefixSum.
> x10:42: Place type error: either method target should be local or 
> method should be global. 
>          Method target: PrefixSum.this.a_prefix_sum 
>          Method target place: null 
>          Current place: PrefixSum#this.home 
>          Method: size
> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/DistPrefixSum.
> x10:61: Place type error: either method target should be local or 
> method should be global. 
>          Method target: DistPrefixSum.this 
>          Method target place: null 
>          Current place: p 
>          Method: place_str
> 4 errors.
> 
> Let's focus on the third error, since that is from the "easiest" 
> implementation (single activity, single place).  The code is attached.
> I think my problem boils down to a lack of understanding about 
> referencing an object's fields and exactly what "this" means. 
> 
> I start out by declaring a class whose objects will allocate an array.
> I provide 3 constructors (a default and 2 initialization 
> constructors).  Constructors seem to use "this" for their definition -
> is that correct?
> 
> public class PrefixSum {
> 
>    val a_prefix_sum:  Array[Int](1);
> 
>     public def this() {
>        a_prefix_sum = new Array[Int]([1..2], (Point)=>0);
>     }
> 
>     public def this(length:Int) {
>        a_prefix_sum = new Array[Int]([1..length], (Point)=>0);
>        for ((i) in a_prefix_sum) {
>           a_prefix_sum([i]) = i;
>        }
>     }
> 
>     public def this(a:Array[Int](1)) 
>     {
>       a_prefix_sum = new Array[Int](a.region, (Point)=>0);
>       for ((i) in a_prefix_sum) {
>          a_prefix_sum([i]) = a([i]);
>       }
>    }
> 
> ...then, I get the following error on the following code:
> 
> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/PrefixSum.
> x10:42: Place type error: either method target should be local or 
> method should be global. 
>          Method target: PrefixSum.this.a_prefix_sum 
>          Method target place: null 
>          Current place: PrefixSum#this.home 
>          Method: size
> 
>    public def str_end():String 
>     {
>       return a_prefix_sum([a_prefix_sum.size()]).toString();
>     }
> 
> So, it looks like accessing the "size" field of a_prefix_sum goes 
> through "this" - which is the class PrefixSum???
> 
> Thanks,
> Dave
> 
> 
> On Jul 29, 2010, at 3:08 PM, Igor Peshansky wrote:
> 
> > Hi, Dave,
> > 
> > You're accessing a field (or calling a method) of a remote object
> > reference.  If you ran the compiler with the -STATIC_CALLS flag,
> > you would have gotten a compile-time error.  As it is, the
> > compiler inserts a dynamic check for you, which then fails at
> > runtime.
> > 
> > Try compiling your program with -STATIC_CALLS, and see what the
> > compiler reports.
> > 
> > Hope this helps,
> >        Igor
> > P.S. Judging by your stack trace, you seem to be running on a Mac.
> > There was a bug with printing Mac stack traces in X10 2.0.5 which
> > is fixed in SVN HEAD (so it will work better in the next release).
> > 
> > Dave Hudak <dhu...@osc.edu> wrote on 07/29/2010 12:53:18 PM:
> > 
> >> Hi All,
> >> 
> >> I took Igor's advice on using a cell to pass results back to the 
> >> calling place.  I recoded my function for translating a distarray 
into
> >> a string as follows.  The "boo/hoo" statements are line counters:
> >> 
> >>    public def place_str(): String
> >>    {
> >>      Console.OUT.println("hoo");
> >>      var s : String = "";                        //var is mutable
> >>      Console.OUT.println("hoo1");
> >>      var first : Boolean = true;                     //var 
> >> declaration must include type
> >>      Console.OUT.println("place_str "+here.id);
> >>      for (pt in a_prefix_sum | here) {
> >>         if (first) {
> >>            first = false;
> >>         }
> >>         else {
> >>            s += ", ";
> >>         }
> >>         Console.OUT.println("place_str point = "+pt);
> >>         s += a_prefix_sum(pt).toString();         //works because 
> >> toString is global
> >>      }
> >>      return s;
> >>    }
> >> 
> >>    public def str():String 
> >>    {
> >>       var s : String = "";                        //var is mutable
> >>      for (p in a_prefix_sum.dist.places()) {
> >>         Console.OUT.println("str "+p.id);
> >>         val z = new Cell[String](null);
> >>         Console.OUT.println("boo");
> >>         val h = here;
> >>         Console.OUT.println("boo2");
> >>         at (p) {
> >>            Console.OUT.println("boo3");
> >>            val q = place_str();
> >>            Console.OUT.println("boo4");
> >>            at (h) z.set(q);
> >>            Console.OUT.println("boo5");
> >>         }
> >>         s += z();
> >>         if (p.id != (Place.MAX_PLACES - 1)) {
> >>            s += ", ";
> >>         } //if
> >>         Console.OUT.println("s = "+s);
> >>      } //for i 
> >>      return s;
> >>   }
> >> 
> >> I am causing an exception when I call the place_str method from any 
> >> place other that place 0.  Here is the output:
> >> 
> >> dhu...@oscnet166 77%> mpirun -np 8 Driver
> >> <...snip>
> >> str 0
> >> boo
> >> boo2
> >> boo3
> >> hoo
> >> hoo1
> >> place_str 0
> >> place_str point = (1)
> >> place_str point = (2)
> >> place_str point = (3)
> >> place_str point = (4)
> >> boo4
> >> boo5
> >> s = 1, 2, 3, 4, 
> >> str 1
> >> boo
> >> boo2
> >> boo3
> >> Uncaught exception at place 0: x10.lang.ClassCastException (home==1): 

> >> DistPrefixSum{self.home==here}
> >> x10.lang.ClassCastException (home==1): DistPrefixSum{self.home==here}
> >>        at x10::lang::Throwable::fillInStackTrace()
> >> 
> >> Any ideas?
> >> 
> >> Thanks,
> >> Dave
> >> On Jul 28, 2010, at 8:05 PM, Igor Peshansky wrote:
> >> 
> >>> Igor Peshansky/Watson/i...@ibmus wrote on 07/28/2010 07:15:02 PM:
> >>> 
> >>>> Dave Hudak <dhu...@osc.edu> wrote on 07/28/2010 02:37:22 PM:
> >>>> 
> >>>>> Hi All,
> >>>>> 
> >>>>> I am trying to write a class that will do a prefix sum on an 
array. 
> > I
> >>>>> have written the single-place version and a single-place version 
> > that 
> >>>>> uses multiple activities to compute the sums.  I am now trying to 
> >>>>> write the distributed version.  Both classes are included (I will 
> >>>>> eventually write an interface for these classes).
> >>>>> 
> >>>>> I have been able to write the constructors and call them without 
> > run-
> >>>>> time exceptions occurring.  Now, I want to write a function that 
> >>>>> returns a single string representation of a dist array.  I wrote a 

> >>>>> function that should create a string representation of all dist 
> > array 
> >>>>> elements at a given location (I called it place_str), and then I 
> > want 
> >>>>> to loop over all places:
> >>>>> 
> >>>>> (from DistPrefixSum.x10):
> >>>>> 
> >>>>>   public def str():String 
> >>>>>   {
> >>>>>      var s : String = "";                        //var is mutable
> >>>>>     for (var place_id:int=0; place_id<Place.MAX_PLACES; 
place_id++) 
> > 
> >>> {
> >>>>>        s += at (Place.places(place_id)) place_str();
> >>>>>        if (place_id != (Place.MAX_PLACES - 1)) {
> >>>>>           s += ", ";
> >>>>>        } //if
> >>>>>     } //for i 
> >>>>>     return s;
> >>>>>  }
> >>>>> 
> >>>>> My error occurs on the at statement:
> >>>>> 
> >>>>> dhu...@oscnet166 35%> x10c++ -O -o Driver Driver.x10 PrefixSum.x10 

> >>>>> AsyncPrefixSum.x10 DistPrefixSum.x10
> >>>>> 
> >>>> 
> >>> 
> >> 
> > 
> 
/Users/dhudak/osc/research/x10/tutorial/examples/GoodPrefixSum/src/DistPrefixSum.
> >>>>> x10:49: Local variable "place_id" is accessed from an inner class 
or 
> > a
> >>>>> closure, and must be declared final or shared.
> >>>>> 1 error.
> >>>>> 
> >>>>> Does anyone have any recommendations?  Creating a single string 
from 
> > a
> >>>>> dist array of integers is a reduction just like finding the sum or 

> > max
> >>>>> of the entries, so I figure its well understood...
> >>>> 
> >>>> Dave,
> >>>> 
> >>>> This is a bug in the typechecking of at expressions.  You can work 
> >>> around
> >>>> this by changing the body of the for loop to
> >>>> 
> >>>>     val z = new Cell[String](null);
> >>>>     val h = here;
> >>>>     at (Place.places(place_id)) { val q = place_str(); at (h) 
> >>> z.set(q); 
> >>>> }
> >>>>     s += z();
> >>>>     if (place_id != (Place.MAX_PLACES - 1)) {
> >>>>       s += ", ";
> >>>>     } //if
> >>>> 
> >>>> The above code is less efficient, but it should work.
> >>>> I've opened a JIRA issue: 
> > http://jira.codehaus.org/browse/XTENLANG-1632 
> >>> .
> >>>> Please watch that issue for updates on the fix.
> >>>>       Igor
> >>> 
> >>> Dave,
> >>> 
> >>> The fix turned out to be simple.  This is now fixed in SVN HEAD 
> > (r15224),
> >>> and will be available in the next X10 release (or you can build from 

> > SVN
> >>> to pick up the fix).
> >>>       Igor
-- 
Igor Peshansky  (note the spelling change!)
IBM T.J. Watson Research Center
X10: Parallel Productivity and Performance (http://x10-lang.org/)
XJ: No More Pain for XML's Gain (http://www.research.ibm.com/xj/)
"I hear and I forget.  I see and I remember.  I do and I understand" -- 
Confucius


------------------------------------------------------------------------------
The Palm PDK Hot Apps Program offers developers who use the
Plug-In Development Kit to bring their C/C++ apps to Palm for a share
of $1 Million in cash or HP Products. Visit us here for more details:
http://p.sf.net/sfu/dev2dev-palm
_______________________________________________
X10-users mailing list
X10-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/x10-users

Reply via email to