Q1:
Whether one of your classes requires the *e**nv* parameter depends on whether you want to create a new Source or set a ExecutionEnvironment parameter inside the class.
If you don't you can of course not pass it :)
I can't see anything that would prevent it form running on a cluster.

Q2:
Usually, parameters are passed to a UDF through the constructor. You /can /use a DataSet within a function initializer block, but it's rather unusual (this is in-fact the first time I've seen it done this way).

You can also just pass a long into the constructor, there is no need to use a DataSet and collect().

final ExecutionEnvironment env =  
ExecutionEnvironment.getExecutionEnvironment();

DataSet<Double> Radius = env.fromElements(10.0); final long numIter = 1000000L; DataSet<Double> pi = new classPI(env).compute(numIter);DataSet<Double> LengthCircle = new classLengthCircle().computeLengthCircle(pi, Radius);

public static final class classPI implements Serializable {
        private final ExecutionEnvironment env;

        public classPI(ExecutionEnvironment env) {
                this.env = env;
        }

        public DataSet<Double> compute( final long numIter) throws Exception {
                return  this.env.generateSequence(1, numIter)
                .map(new Sampler())
                .reduce(new SumReducer())
                .map(new MapFunction<Long, Double >() {
                        @Override
                        public Double map(Long arg0) throws Exception {
                                return arg0 *4.0/numIter;
                        }});
        }
}

Regards,
Chesnay


//On 10.06.2016 02:46, Ser Kho wrote:
Chesnay:
I have two simple questions, related to the previous ones about encapsulation of transformations.

Question 1. I have tried to extend my code using your suggestions and come up with a small concern. First, your code:
|publicstaticvoidmain(String[]args)throwsException{ ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); *DataSet<Double> **pi =new classPI(env).compute();*new classThatNeedsPI(env).computeWhatever(pi); //append your transformations to pi env.execute(); } |
|
|
|
|
Below is my code (the bold lines are very similar and work ok). The line of concern is marked by blue color. The issue is that I do not use*env* in the constructor of the class classLengthCircle(),instead I use DataSet *pi* in the methodcomputeLengthCircle(pi, Radius) and also DataSet Radius, but the latter does not matter for the question. Then, I proceed with transformations using this DataSet***pi,* see the**class classLengthCircle below. It seems that the logic of this class and its method computeLengthCircle() does not require env at all. My question is if this code work will on a cluster (it does work on a local computer)?

final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment();
        DataSet<Double> Radius = env.fromElements(10.0);
        DataSet<Long>    NumIter =env.fromElements(1000000L);
        // this line is similar to the suggested
* DataSet<Double> pi = new classPI(env).compute(NumIter);*
// this line is somewhat different from the suggested, as it has no env in the constructor DataSet<Double> LengthCircle = new classLengthCircle().computeLengthCircle(pi, Radius);
=========================
public static final class classLengthCircle
    {
public DataSet<Double> computeLengthCircle(DataSet<Double> pi, DataSet<Double> Radius)
        {
 DataSet<Double> result = pi.cross(Radius).map(
 new MapFunction<Tuple2<Double, Double>, Double >() {
@Override
public Double map(Tuple2<Double, Double> arg0) throws Exception {
return 2*arg0.f0 *arg0.f1;
}}
 );
return result;
       }
    }
================================================
Question 2:
I tried to enter a parameter *DataSet NumIter* into a class *MapFunction* of transformation *map(), *see the blue mark in the code below. It seems this parameter appears in the MapFunction without explicit passing, since nowhere the line
 .map(new MapFunction<Long, Double >()
has any mentioning of NumIter.
Is the suggested approach a right way to pass a parameter inside the transformation MapFunction ?
Note, that the code works all right on a single computer.

public static final class classPI implements Serializable
   {
private final ExecutionEnvironment env;
publicclassPI(ExecutionEnvironment env) {this.env = env;}
public DataSet<Double> compute( final DataSet<Long> NumIter) throws Exception{
return  this.env.generateSequence(1, NumIter.collect().get(0))
.map(new Sampler())
.reduce(new SumReducer())
.map(new MapFunction<Long, Double >()
{
*Long N = NumIter.collect().get(0);*
@Override
public Double map(Long arg0) throws Exception {
return arg0 *4.0/N;
}}); }}

Thanks a lot for your time.
Ser



On Tuesday, June 7, 2016 8:14 AM, Chesnay Schepler <[email protected]> wrote:


1a. ah. yeah i see how it could work, but i wouldn't count on it in a cluster. you would (most likely) run the the sub-job (calculating pi) only on a single node.

1b. different execution environments generally imply different flink programs.

2. sure it does, since it's a normal flink job. yours on the other hand doesn't, since the job calculating PI only runs on a single TaskManager.

3. there are 2 ways. you can either chain jobs like this: (effectively running 2 flink programs in succession) |publicstaticvoidmain(String[]args)throwsException{doublepi =new classPI().compute();System.out.println("We estimate Pi to be: " +pi); new classThatNeedsPI().computeWhatever(pi); //feeds pi into an env.fromElements call and proceeds from there }|
or (if all building blocks are flink programs) build a single job:
|publicstaticvoidmain(String[]args)throwsException{ ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); DataSet<Double> pi =new classPI(env).compute();new classThatNeedsPI(env).computeWhatever(pi); //append your transformations to pi env.execute(); } ... ||publicDataSet<Double>compute()throwsException{return this.env.generateSequence(1,NumIter).map(newSampler()).reduce(newSumReducer()) .map(/*return 4 * x*/);} ... public ? computeWhatever(DataSet<Long> pi) throws Exception { ... } |

On 07.06.2016 13:35, Ser Kho wrote:
Chesnay:
1a. The code actually works, that is the point.
1b. What restrict for a Flink program to have several execution environments?
2. I am not sure that your modification allows for parallelism. Does it?
3. This code is a simple example of writing/organizing large and complicated programs, where the result of this pi needed to be used in another DataSet transformations beyond classPi(). What to do in this case?
Thanks a lot for the suggestions.


On Tuesday, June 7, 2016 6:15 AM, Chesnay Schepler <[email protected]> <mailto:[email protected]> wrote:


from what i can tell from your code you are trying to execute a job within a job. This just doesn't work.

your main method should look like this:

|publicstaticvoidmain(String[]args)throwsException{doublepi =new classPI().compute();System.out.println("We estimate Pi to be: " +pi);}|



On 06.06.2016 21:14, Ser Kho wrote:
The question is how to encapsulate numerous transformations into one object or may be a function in Apache Flink Java setting. I have tried to investigate this question using an example of Pi calculation (see below). I am wondering whether or not the suggested approach is valid from the Flink's point of view. It works on one computer, however, I do not know how it will behave in a cluster setup. The code is given below, and the main idea behind it as follows:

 1. Create a class, named classPI, which method compute() does all
    data transformations, see more about it below.
 2. In the main method create a DataSet as in *DataSet< classPI >
    opi = env.fromElements(new classPI());*
3.
    Create *DataSet< Double > PI*, which equals output of
    transformation map() that calls the object PI's method compute()
    as in
    *DataSet< Double > PI = opi.map(new MapFunction< classPI ,
    Double>() { public Double map(classPI objPI) { return
    objPI.compute(); }});*
4.
    Now about ClassPI
     *
        Constructor instantiates ExecutionEnvironment, which is
        local for this class, as in
        *public classPI(){ this.NumIter=1000000; env =
        ExecutionEnvironment.getExecutionEnvironment();}*

Thus, the code has two ExecutionEnvironment objects: one in main and another in the class classPI.

 *
    Has method compute() that runs all data transormations (in this
    example it is just several lines but potentially it might
    contain tons of Flink transfromations)
    *public Double compute(){ DataSet count =
    env.generateSequence(1, NumIter) .map(new Sampler()) .reduce(new
    SumReducer()); PI = 4.0*count.collect().get(0)/NumIter;
    return PI;}*

the whole code is given below. Again, the question is if this is a valid approach for encapsulation of data transformation into a class in Flink setup that is supposed to be parallelizable to work on a cluster. Is there a better way to hide details of data transformations?
Thanks a lot!

-------------------------The code ----------------------

|public< span id="yiv9579689340yui_3_16_0_ym19_1_1465213860132_46078" style="margin:0px;border:0px;color:rgb(16, 16, 148);">classPiEstimation{publicstaticvoidmain(String[]args)throwsException{// this is one ExecutionEnvironmentfinalExecutionEnvironmentenv =ExecutionEnvironment .getExecutionEnvironment();// this is critical DataSet with my classPI that computes PIDataSet<classPI>opi =env.fromElements(newclassPI());// this map calls the method compute() of class classPI that computes PIDataSet<Double>PI =opi.map(newMapFunction<classPI ,Double>(){publicDoublemap(classPI objPI)throwsException{// this is how I call method compute() that calculates PI using transformations returnobjPI.compute();}});doublepi =PI.collect().get(0);System.out.println("We estimate Pi to be: " +pi);}// this class is of no impotance for my question, howerver, it is relevant for pi calculation publicstaticclassSamplerimplementsMapFunction<Long,Long>{@OverridepublicLongmap(Longvalue){doublex =Math.random();doubley =Math.random();return(x *x +y *y)<1?1L:0L;}}// this class is of no impotance for my question, howerver, it is relevant for pi calculation publicstaticfinalclassSumReducerimplementsReduceFunction<Long>{@OverridepublicLongreduce(Longvalue1,Longvalue2){returnvalue1 +value2;}}// this is my class that computes PI, my question is whether such a class is valid in Flink on cluster with parallel computation publicstaticfinalclassclassPI {publicIntegerNumIter;privatefinalExecutionEnvironmentenv;publicDoublePI;// this is constructor with another ExecutionEnvironmentpublicclassPI(){this.NumIter=1000000;env =ExecutionEnvironment.getExecutionEnvironment();}//This is the the method that contains all data transformationpublicDoublecompute()throwsException{DataSet<Long>count =env.generateSequence(1,NumIter).map(newSampler()) .reduce(newSumReducer()) ;PI =4.0*count.collect().get(0)/NumIter;returnPI;}}}|







Reply via email to