简体   繁体   English

如何修复 Java 中的可调用重叠?

[英]How can I fix callable overlapping in Java?

I'm not sure whether the title is detail/correct or not but i can't figure out how to describe it in the title so I will try my best to describe it here我不确定标题是否详细/正确,但我不知道如何在标题中描述它,所以我会尽力在这里描述它

I've been trying to use callable in Java for concurrency, but the outcome is not correct, seem like the thread has been over lapping each other while running...below is the call function for that我一直在尝试在 Java 中使用 callable 进行并发,但结果不正确,似乎线程在运行时相互重叠……下面是调用函数

@Override
public String call() {
    String result = "yay";
    long startTime = System.currentTimeMillis();
    long endTime = startTime + timeOutMiliseconds * 1000;
    while (System.currentTimeMillis() < endTime) {
        int[] currentMapping = generateTpuMappingWithRange(ia, startRange, stopRange);
        System.out.println(" current - " + Arrays.toString(currentMapping) + " - " +  ID);
        result = Arrays.toString(currentMapping);
    }
    return result;
}

generateTpuMappingWithRange() function is just generate another random integer array with the first index from startRange -> stopRange generateTpuMappingWithRange()函数只是生成另一个随机整数数组,第一个索引从 startRange -> stopRange

(ie startRange = 0, stopRange = 2, then [0, 2, 1,] -> [1, 2, 1] or [2,2,1]) (即 startRange = 0,stopRange = 2,然后 [0, 2, 1,] -> [1, 2, 1] 或 [2,2,1])

constructor构造函数

public MarkovTest(int ID, int startRange, int stopRange) {
    this.ID = ID;
    this.startRange = startRange;
    this.stopRange = stopRange;
    init();
}

Here is main这里是主要的

public static void main(String[] args) throws InterruptedException, ExecutionException {
    Callable<String> Array = new MarkovTest(1, 0, 1);
    Callable<String> Array2 = new MarkovTest(2, 2, 3);
    Callable<String> Array3 = new MarkovTest(3, 4, 5);

    List<Callable<String>> taskList = Arrays.asList(Array,Array2,Array3);

    List<Future<String>> future = executor.invokeAll(taskList);
    for(Future<String> result : future)
    {
        System.out.println(result.get());
    }
}

the number in the last is the ID variable is to check whether it's printing out the correct one or not...however here is the problem, in the console, this happen...最后一个数字是ID变量是为了检查它是否打印出正确的一个...但是这里有问题,在控制台中,这发生了...

 current - [0, 3, 5, 0, 5, 4, 3, 2, 1, 4, 6, 1, 3, 6] - 1
 current - [1, 3, 5, 0, 5, 4, 3, 2, 1, 4, 6, 1, 3, 6] - 3
 current - [0, 3, 5, 0, 5, 4, 2, 2, 0, 4, 6, 1, 3, 6] - 1
 current - [0, 3, 5, 0, 5, 4, 3, 2, 0, 4, 6, 1, 3, 6] - 2

1st line is correct, ID 1 should print array with first index in range 0 to 1. But ID 3 and 2 should not have the 0 or 1 in the first index...this doesn't happen all the time but will appear here and there among thousand of console output第一行是正确的,ID 1 应该打印第一个索引在 0 到 1 范围内的数组。但是 ID 3 和 2 在第一个索引中不应该有 0 或 1 ......这不会一直发生,但会出现在这里并且在数千个控制台输出中

Any idea why is this happening?知道为什么会这样吗? I'm really stressed because of this...T__T因为这个我真的很紧张...T__T

Edit: Added generateTpuMappingWithRange编辑:添加了generateTpuMappingWithRange

private int[] generateTpuMappingWithRange(int[] iap, int startRange, int stopRange) {
    final Logger log = Logger.getLogger(MarkovTest.class);

    int maximumNoOfCoreIndex = 6;
    int minimumNoOfCoreIndex = 0;
    int firstIndex = 0;
    int[] result = iap;
    log.debug("OLD MAPPING = " + Arrays.toString(result));
    // generate random
    Random randomNum = new Random();
    // generate number from 0 -> 13 (because last number will always be 6)
    int randomIndex = randomNum.nextInt(iap.length - 1);
    // last one will always be 6 so dont need to include that
    int minusOrPlus = 0;
    minusOrPlus = randomNum.nextBoolean() ? 1 : -1;
    Task thisTask = this.model.getSwModel().getTasks().get(randomIndex);
    PuType thisTaskPuType = domains.get(thisTask);
    int[] newIndexValueRange = this.intervals.get(thisTaskPuType);

    minimumNoOfCoreIndex = newIndexValueRange[0];
    maximumNoOfCoreIndex = newIndexValueRange[1];
    int newIndexValue = result[randomIndex] + minusOrPlus;
    // Split 0-1, 2-3, 4-5 for 3 markov chain.
    if (randomIndex == firstIndex) {
        if (newIndexValue > stopRange) {
            newIndexValue = startRange;
        } else if (newIndexValue < startRange) {
            newIndexValue = stopRange;
        }
    } else {
        if (newIndexValue > maximumNoOfCoreIndex) {
            newIndexValue = minimumNoOfCoreIndex;
        } else if (newIndexValue < minimumNoOfCoreIndex) {
            newIndexValue = maximumNoOfCoreIndex;
        }
    }
    // if the new index value generated from line above surpass our maximum no of
    // core, then it will return to number 0
    // This may resolve to infinite loop if THE SAME randomIndex appear again and
    // again and again and again, which hopefully wont be a thing for this
    // implementation

    result[randomIndex] = newIndexValue;
    log.debug("NEW MAPPING = " + Arrays.toString(result));
    log.debug(" location =" + randomIndex + " value =" + newIndexValue);
    return result;
}

Here is the full Version of the code just in case.这是代码的完整版本,以防万一。

init() method is basically generate 2 HashMap, mainly used to determine the maxmimum and minimum value for each index. init()方法基本上就是生成2个HashMap,主要用于确定每个索引的最大值和最小值。

public class MarkovTest implements Callable<String> {
static ExecutorService executor = Executors.newFixedThreadPool(3);

int startRange;
int stopRange;
long timeOutMiliseconds = 1000;
long maxIteration;
Amalthea model;
int[] ia;
int ID;
private final int nbCPUs;
private final int nbPUs;
private final HashMap<Task, PuType> domains = new HashMap<Task, PuType>();
private final HashMap<PuType, int[]> intervals = new HashMap<PuType, int[]>();   

public MarkovTest(int[] ia, Amalthea model, int ID, int startRange, int stopRange) {
    this.model = model;
    this.ia = ia;
    this.nbCPUs = CommonUtils.getNumberofCPUs(model);
    // this.nbGPUs = CommonUtils.getNumberofGPUs(this.model);
    this.nbPUs = CommonUtils.getNumberofPUs(model);
    this.ID = ID;
    this.startRange = startRange;
    this.stopRange = stopRange;
    init();
}

public static void main(String[] args) throws InterruptedException, ExecutionException {
    org.apache.log4j.BasicConfigurator.configure();
    Logger.getRootLogger().setLevel(Level.INFO);
    long startTime = System.currentTimeMillis();
    int[] ia = { 5, 2, 5, 3, 3, 1, 3, 5, 1, 0, 0, 6, 4, 6 };
    final Amalthea ama = AmaltheaLoader.loadFromFile(new File(SharedConsts.ECRTS_MODEL));

    Callable<String> Array = new MarkovTest(ia, ama, 1, 0, 1);
    Callable<String> Array2 = new MarkovTest(ia, ama, 2, 2, 3);
    Callable<String> Array3 = new MarkovTest(ia, ama, 3, 4, 5);

    List<Callable<String>> taskList = Arrays.asList(Array,Array2,Array3);

    List<Future<String>> future = executor.invokeAll(taskList);
    for(Future<String> result : future)
    {
        System.out.println(result.get());
    }
    long endTime = System.currentTimeMillis();
    long elapsedTime = endTime - startTime;
    System.out.println(" elapsed Time = " + elapsedTime);
    System.out.println("Done");
}

@Override
public String call() {
    String result = "yay";
    long startTime = System.currentTimeMillis();
    long endTime = startTime + timeOutMiliseconds * 1000;
    while (System.currentTimeMillis() < endTime) {
        int[] currentMapping = generateTpuMappingWithRange(ia, startRange, stopRange);
        System.out.println(" current - " + Arrays.toString(currentMapping) + " - " +  ID);
        result = Arrays.toString(currentMapping);
    }
    return result;
}

private int[] generateTpuMappingWithRange(int[] iap, int startRange, int stopRange) {
    final Logger log = Logger.getLogger(MarkovTest.class);

    int maximumNoOfCoreIndex = 6;
    int minimumNoOfCoreIndex = 0;
    int firstIndex = 0;
    int[] result = iap;
    log.debug("OLD MAPPING = " + Arrays.toString(result));
    // generate random
    Random randomNum = new Random();
    // generate number from 0 -> 13 (because last number will always be 6)
    int randomIndex = randomNum.nextInt(iap.length - 1);
    // last one will always be 6 so dont need to include that
    int minusOrPlus = 0;
    minusOrPlus = randomNum.nextBoolean() ? 1 : -1;
    Task thisTask = this.model.getSwModel().getTasks().get(randomIndex);
    PuType thisTaskPuType = domains.get(thisTask);
    int[] newIndexValueRange = this.intervals.get(thisTaskPuType);

    minimumNoOfCoreIndex = newIndexValueRange[0];
    maximumNoOfCoreIndex = newIndexValueRange[1];
    int newIndexValue = result[randomIndex] + minusOrPlus;
    // Split 0-4, 5-10, 11-13 for 3 markov chain.
    if (randomIndex == firstIndex) {
        if (newIndexValue > stopRange) {
            newIndexValue = startRange;
        } else if (newIndexValue < startRange) {
            newIndexValue = stopRange;
        }
    } else {
        if (newIndexValue > maximumNoOfCoreIndex) {
            newIndexValue = minimumNoOfCoreIndex;
        } else if (newIndexValue < minimumNoOfCoreIndex) {
            newIndexValue = maximumNoOfCoreIndex;
        }
    }
    // if the new index value generated from line above surpass our maximum no of
    // core, then it will return to number 0
    // This may resolve to infinite loop if THE SAME randomIndex appear again and
    // again and again and again, which hopefully wont be a thing for this
    // implementation

    result[randomIndex] = newIndexValue;
    log.debug("NEW MAPPING = " + Arrays.toString(result));
    log.debug(" location =" + randomIndex + " value =" + newIndexValue);
    return result;
}

private void init() {
    final Logger log = Logger.getLogger(CallableForMarkov.class);
    for (final Task t : this.model.getSwModel().getTasks()) {
        boolean cpu = false;
        boolean gpu = false;
        boolean defaultVal = false;
        for (final CallGraphItem geb : t.getCallGraph().getItems()) {
            if (geb instanceof Group) {
                final Group cs = (Group) geb;
                for (final CallGraphItem csi : cs.getItems()) {
                    if (csi instanceof RunnableCall) {
                        final RunnableCall trc = (RunnableCall) csi;
                        for (final CallGraphItem ri : trc.getRunnable().getRunnableItems()) {
                            if (ri instanceof Ticks) {
                                final Ticks ticks = (Ticks) ri;
                                if (null != ticks.getDefault() && ticks.getDefault().getAverage() > 0) {
                                    defaultVal = true;
                                }
                                for (final Entry<ProcessingUnitDefinition, IDiscreteValueDeviation> e : ticks
                                        .getExtended().entrySet()) {
                                    if (!gpu && e.getKey().getPuType().equals(PuType.GPU)) {
                                        gpu = true;
                                    } else if (!cpu && e.getKey().getPuType().equals(PuType.CPU)) {
                                        cpu = true;
                                    }
                                }
                            }
                        }
                        // TODO check if there are runnables with different tick vals
                    }
                }
            }
        }
        if (cpu && !gpu) {
            /* task can be mapped only to CPUs */
            log.debug(t.getName() + " can be mapped to 0 --" + (this.nbCPUs - 1));
            this.domains.put(t, PuType.CPU);
            if (!this.intervals.containsKey(PuType.CPU)) {
                this.intervals.put(PuType.CPU, new int[] { 0, this.nbCPUs - 1 });
            }
        } else if (gpu && !cpu) {
            /* task can be mapped only to GPUs */
            log.debug(t.getName() + " can be mapped to " + this.nbCPUs + "--" + (this.nbPUs - 1));
            this.domains.put(t, PuType.GPU);
            if (!this.intervals.containsKey(PuType.GPU)) {
                this.intervals.put(PuType.GPU, new int[] { this.nbCPUs, this.nbPUs - 1 });
            }
        } else if (defaultVal || (gpu && cpu)) {
            /* task can be mapped anywhere */
            log.debug(t.getName() + " can be mapped to 0 --" + (this.nbPUs - 1));
            this.domains.put(t, PuType._UNDEFINED_);
            if (!this.intervals.containsKey(PuType._UNDEFINED_)) {
                this.intervals.put(PuType._UNDEFINED_, new int[] { 0, this.nbPUs - 1 });
            }
        } else {
            /* Task can be mapped nowhere */
            log.fatal(t.getName() + " can be mapped nowhere");
        }
    }
}

} }

Take a look at my inline comments within your code excerpts:看看我在代码摘录中的内联注释:

public static void main(String[] args) throws InterruptedException, ExecutionException {
    org.apache.log4j.BasicConfigurator.configure();
    Logger.getRootLogger().setLevel(Level.INFO);
    long startTime = System.currentTimeMillis();   

    //-----> You have created an instance of ia
    int[] ia = { 5, 2, 5, 3, 3, 1, 3, 5, 1, 0, 0, 6, 4, 6 };
    final Amalthea ama = AmaltheaLoader.loadFromFile(new File(SharedConsts.ECRTS_MODEL));  

//-----> You have passed the _same_ instance to all of the constructor calls
    Callable<String> Array = new MarkovTest(ia, ama, 1, 0, 1);
    Callable<String> Array2 = new MarkovTest(ia, ama, 2, 2, 3);
    Callable<String> Array3 = new MarkovTest(ia, ama, 3, 4, 5);  
    ...    

 //---->lets move a bit down to the method that's called within the Callable  

private int[] generateTpuMappingWithRange(int[] iap, int startRange, int stopRange) {  
   ...    
  int firstIndex = 0;
   ...  
   int randomIndex = random.nextInt(iap.length - 1);  
   ...  
 //---> this part should make sure what you are stating, that "ID 1 should print array with first index in range 0 to 1." and this is correct
   if (randomIndex == firstIndex) {

        if (newIndexValue > stopRange) {
            newIndexValue = startRange;
        } else if (newIndexValue < startRange) {
            newIndexValue = stopRange;
        }

    }  else {
        if (newIndexValue > maximumNoOfCoreIndex) {
            newIndexValue = minimumNoOfCoreIndex;
        } else if (newIndexValue < minimumNoOfCoreIndex) {
            newIndexValue = maximumNoOfCoreIndex;
        }
    }
       ...

However, as I mentioned in the code above, you have passed the same ia instance to all of the constructor calls.但是,正如我在上面的代码中提到的,您已将相同的ia实例传递给所有构造函数调用。

This means that all 3 MarkovTest instance will operate on the same ia , modifying it individually, so the rule you have set regarding to the first element of the array does not work.这意味着所有 3 个MarkovTest实例都将在同一个ia ,单独修改它,因此您为数组的第一个元素设置的规则不起作用。

For example, when a MarkovTest with ID=2 got a randomIndex == firstIndex , so it modifies the ia 's first index accordingly, then it prints ia with the updated and correct new first value .例如,当一个MarkovTestID=2得到了一个randomIndex == firstIndex ,所以它修改ia的第一索引相应,然后它打印ia更新和正确的新的第一值

After that, a MarkovTest with ID=1 runs, which gets randomIndex != firstIndex , so it modifies the value of ia at randomIndex , then prints ia , with the previously updated and now incorrect first value , along with the untouched values as well as the correctly updated new value at randomIndex .之后,一个ID=1MarkovTest运行,它得到randomIndex != firstIndex ,所以它在randomIndex处修改ia的值,然后打印ia ,带有先前更新但现在不正确的第一个值,以及未触及的值以及在randomIndex正确更新的新值。

This cycle repeats till System.currentTimeMillis() < endTime for each MarkovTest .这个循环重复直到System.currentTimeMillis() < endTime对于每个MarkovTest

Solution:解决方案:

There are several solutions, as you pass the same instance to all 3 MarkovTest , you can initialize ia directly within the class, and no need for that constructor parameter.有几种解决方案,当您将相同的实例传递给所有 3 个MarkovTest ,您可以直接在类中初始化ia ,而无需该构造函数参数。

If you insist on having the constructor parameter, then you can:如果您坚持使用构造函数参数,那么您可以:

int[] ia_copy;  

public MarkovTest(int[] ia, Amalthea model, int ID, int startRange, int stopRange) {
    this.model = model;  

    //----> create a copy like this:
    ia_copy=new int[ia.length];
    System.arraycopy( ia, 0, ia_copy, 0, ia.length );  

    this.nbCPUs = CommonUtils.getNumberofCPUs(model);
    // this.nbGPUs = CommonUtils.getNumberofGPUs(this.model);
    this.nbPUs = CommonUtils.getNumberofPUs(model);
    this.ID = ID;
    this.startRange = startRange;
    this.stopRange = stopRange;
    init();
}

Just don't forget to change all the references, especially at:只是不要忘记更改所有引用,尤其是在:

@Override
public String call() {
...
while (System.currentTimeMillis() < endTime) {  
//----> ia to ia_copy 
        int[] currentMapping = generateTpuMappingWithRange(ia_copy , startRange, stopRange);  
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM