X10 x10.lang.FailedDynamicCheckException: !(here == x$0.home) C++ Backend

194 views Asked by At

i'm playing around with X10 currently, and i'm getting multiple exceptions. This is the code i created:

Main.x10

public class Main {

// main Method for the Main class
public static def main(argv:Rail[String]) {
    Console.OUT.println("This is the main place. (ID="+here.id+")");
    val dataItem = new Data();
    // no global reference, data is copied to each place.
    finish for (p in Place.places()) {
        at (p) async {
            Console.OUT.println("This is place no: "+here.id+". The value of dataItem is "+dataItem.getValue()+".");
            dataItem.incValue();
        }
    }
    Console.OUT.println("Final value of dataItem without GlobalRef in multiple places at place "+here.id+": "+dataItem.getValue());
    dataItem.setValue(0);
    finish for (p in Place.places()) {
        async {
            Console.OUT.println("This is place no: "+here.id+". The value of dataItem is "+dataItem.getValue()+".");
            dataItem.incValue();
        }
    }
    Console.OUT.println("Final value of dataItem without GlobalRef in one place at place "+here.id+": "+dataItem.getValue());
    dataItem.setValue(0);
    val globalRefDataItem = GlobalRef[Data](dataItem);
    finish for (p in Place.places()) {
        at (p) async {
            val globalDataItemUnwrapped = globalRefDataItem();
            Console.OUT.println("This is place no: "+here.id+". The value of dataItem is "+globalDataItemUnwrapped.getValue()+".");
            atomic globalDataItemUnwrapped.incValue();
        }
    }
    Console.OUT.println("Final value of dataItem with GlobalRef in multiple places at place "+here.id+": "+dataItem.getValue());
}

}

Data.x10

public class Data{
private var value:Long;
def getValue():Long{
    return value;
}
def setValue(value:long){
    this.value = value;
}
def incValue(){
    this.value = this.value+1;
}
}

The output in X10DT is the following:

This is the main place. (ID=0)
This is place no: 3. The value of dataItem is 0.
This is place no: 1. The value of dataItem is 0.
This is place no: 2. The value of dataItem is 0.
This is place no: 0. The value of dataItem is 0.
Final value of dataItem without GlobalRef in multiple places at place 0: 0
This is place no: 0. The value of dataItem is 0.
This is place no: 0. The value of dataItem is 1.
This is place no: 0. The value of dataItem is 2.
This is place no: 0. The value of dataItem is 3.
Final value of dataItem without GlobalRef in one place at place 0: 4
This is place no: 0. The value of dataItem is 0.
Command used: /home/martze/x10dt/workspace/Example/bin/Main
Uncaught exception at place 0: x10.lang.MultipleExceptions
x10.lang.FailedDynamicCheckException: !(here == x$0.home)
at x10aux::throwException(x10::lang::CheckedThrowable*)
at Main__closure__3::__apply()
at x10::lang::Activity::run()
at x10::lang::Runtime__Worker::loop()
at x10::lang::Runtime__Worker::__apply()
at x10::lang::Runtime__Pool::run()
at 
at GC_inner_start_routine
at GC_call_with_stack_base
at 
at clone
x10.lang.FailedDynamicCheckException: !(here == x$0.home)
at x10aux::throwException(x10::lang::CheckedThrowable*)
at Main__closure__3::__apply()
at x10::lang::Activity::run()
at x10::lang::Runtime__Worker::loop()
at x10::lang::Runtime__Worker::__apply()
at x10::lang::Runtime__Pool::run()
at 
at GC_inner_start_routine
at GC_call_with_stack_base
at 
at clone
x10.lang.FailedDynamicCheckException: !(here == x$0.home)
at x10aux::throwException(x10::lang::CheckedThrowable*)
at Main__closure__3::__apply()
at x10::lang::Activity::run()
at x10::lang::Runtime__Worker::loop()
at x10::lang::Runtime__Worker::__apply()
at x10::lang::Runtime__Pool::run()
at 
at GC_inner_start_routine
at GC_call_with_stack_base
at 
at clone

I tried googling, but the results were only pointing to some documentation that didn't help me at all. My environment variables are set to X10_NTHREADS=1 and i set the number of places to 4. I'm working with Ubuntu and i'm using the C++ Backend.

What can i do about this error and what does this error mean?

1

There are 1 answers

2
Josh Milthorpe On BEST ANSWER

A GlobalRef is a globally meaningful reference to an object at a particular place. It may only be dereferenced at the place where it was created (the "home" place). The exception is thrown at the dereferencing ('unwrapping') of the GlobalRef:

val globalRefDataItem = GlobalRef[Data](dataItem);
finish for (p in Place.places()) {
  at (p) async {
    val globalDataItemUnwrapped = globalRefDataItem();
    ...
  }
}

The GlobalRef was created at place 0, but is being dereferenced (globalRefDataItem()) at place p. The error would be easier to understand if it read:

x10.lang.FailedDynamicCheckException: (here != globalRefDataItem.home)

To access the object that is referred to by the GlobalRef, the activity must change place back to the home place. For example:

val globalRefDataItem = GlobalRef[Data](dataItem);
finish for (p in Place.places()) {
  at (p) async {
    at(globalRefDataItem.home) {
      atomic globalDataItemUnwrapped.incValue();
    }
  }
}

This is often referred to as the "ping-pong" idiom - the activity changes to a remote place and then changes back again to the original place.

In your program, there is the added requirement to print the value of dataItem before it was incremented. To do this, use an at expression (X10 language spec ยง13.3) to return a value from the remote place, for example:

finish for (p in Place.places()) {
  at (p) async {
    val currentValue = at(globalRefDataItem.home) {
      val globalDataItemUnwrapped = globalRefDataItem();
      var valueBeforeInc:Long = 0;
      atomic {
        valueBeforeInc = globalDataItemUnwrapped.getValue();
        globalDataItemUnwrapped.incValue();
      }
      valueBeforeInc
    };
    Console.OUT.println("This is place no: "+here.id+". The value of dataItem is "+currentValue+".");
  }
}

Note, I made an important change to the original code, to combine the get and increment of the value in a single atomic block. Without this change, it would be possible for another activity to increment the value in between these two statements. X10 provides atomic types (e.g. x10.util.concurrent.AtomicLong) which provide just such an atomic getAndIncrement operation.