1 package Analysis.Scheduling;
3 import Analysis.TaskStateAnalysis.*;
6 import Util.GraphNode.SCC;
8 import java.io.FileInputStream;
11 /** This class holds flag transition diagram(s) can be put on one core.
13 public class ScheduleAnalysis {
16 TaskAnalysis taskanalysis;
18 Vector<ScheduleNode> scheduleNodes;
19 Vector<ClassNode> classNodes;
20 Vector<ScheduleEdge> scheduleEdges;
21 Hashtable<ClassDescriptor, ClassNode> cd2ClassNode;
22 boolean sorted = false;
26 int scheduleThreshold;
28 Vector<Vector<ScheduleNode>> scheduleGraphs;
30 // Main CD table for multi-param tasks
31 Hashtable<TaskDescriptor, ClassDescriptor> td2maincd;
33 public ScheduleAnalysis(State state,
34 TaskAnalysis taskanalysis) {
36 this.taskanalysis = taskanalysis;
37 this.scheduleNodes = new Vector<ScheduleNode>();
38 this.classNodes = new Vector<ClassNode>();
39 this.scheduleEdges = new Vector<ScheduleEdge>();
40 this.cd2ClassNode = new Hashtable<ClassDescriptor, ClassNode>();
41 this.transThreshold = 45; // defaultly 45
42 this.scheduleThreshold = 1000; // defaultly 1000
44 this.scheduleGraphs = null;
45 this.td2maincd = null;
48 public void setTransThreshold(int tt) {
49 this.transThreshold = tt;
52 public void setScheduleThreshold(int stt) {
53 this.scheduleThreshold = stt;
56 public int getCoreNum() {
60 public void setCoreNum(int coreNum) {
61 this.coreNum = coreNum;
64 public Vector<Vector<ScheduleNode>> getScheduleGraphs() {
65 return this.scheduleGraphs;
69 public Vector<ScheduleEdge> getSEdges4Test() {
73 public Hashtable<TaskDescriptor, ClassDescriptor> getTd2maincd() {
75 /*Iterator<TaskDescriptor> key = td2maincd.keySet().iterator();
76 while(key.hasNext()) {
77 TaskDescriptor td = key.next();
78 System.err.println(td.getSymbol() + ", maincd: "
79 + this.td2maincd.get(td).getSymbol());
85 public boolean schedule(int generateThreshold,
86 Vector<TaskDescriptor> multiparamtds) {
87 boolean tooptimize = true;
89 Vector<ScheduleEdge> toBreakDown = new Vector<ScheduleEdge>();
90 ScheduleNode startupNode = null;
92 if((multiparamtds != null) || (multiparamtds.size() > 0)) {
93 this.td2maincd = new Hashtable<TaskDescriptor, ClassDescriptor>();
96 // necessary preparation such as read profile info etc.
99 startupNode = buildCFSTG(toBreakDown, multiparamtds);
101 treeTransform(toBreakDown, startupNode);
102 // do CFSTG transform to explore the potential parallelism as much
105 // mappint to real multi-core processor
106 tooptimize = coreMapping(generateThreshold);
108 } catch (Exception e) {
115 private void preSchedule() {
116 this.checkBackEdge();
118 // set up profiling data
119 if(state.USEPROFILE) {
120 java.util.Hashtable<String, TaskInfo> taskinfos =
121 new java.util.Hashtable<String, TaskInfo>();
122 this.readProfileInfo(taskinfos);
125 Iterator it_classes = state.getClassSymbolTable().getDescriptorsIterator();
126 while(it_classes.hasNext()) {
127 ClassDescriptor cd = (ClassDescriptor) it_classes.next();
129 Vector rootnodes = this.taskanalysis.getRootNodes(cd);
130 if(rootnodes!=null) {
131 Iterator it_rootnodes = rootnodes.iterator();
132 while(it_rootnodes.hasNext()) {
133 FlagState root = (FlagState)it_rootnodes.next();
134 Vector allocatingTasks = root.getAllocatingTasks();
135 if(allocatingTasks != null) {
136 for(int k = 0; k < allocatingTasks.size(); k++) {
138 (TaskDescriptor)allocatingTasks.elementAt(k);
139 Vector<FEdge> fev = this.taskanalysis.getFEdgesFromTD(td);
140 int numEdges = fev.size();
141 for(int j = 0; j < numEdges; j++) {
142 FEdge pfe = fev.elementAt(j);
143 TaskInfo taskinfo = taskinfos.get(td.getSymbol());
144 tint = taskinfo.m_exetime[pfe.getTaskExitIndex()];
145 pfe.setExeTime(tint);
147 taskinfo.m_probability[pfe.getTaskExitIndex()];
148 pfe.setProbability(idouble);
150 int tindex = pfe.getTaskExitIndex();
151 if((taskinfo.m_newobjinfo.elementAt(tindex) != null)
152 && (taskinfo.m_newobjinfo.elementAt(tindex).containsKey(
154 newRate = taskinfo.m_newobjinfo.elementAt(tindex).get(
157 pfe.addNewObjInfo(cd, newRate, idouble);
158 if(taskinfo.m_byObj != -1) {
159 ((FlagState)pfe.getSource()).setByObj(taskinfo.m_byObj);
168 Iterator it_flags = this.taskanalysis.getFlagStates(cd).iterator();
169 while(it_flags.hasNext()) {
170 FlagState fs = (FlagState)it_flags.next();
171 Iterator it_edges = fs.edges();
172 while(it_edges.hasNext()) {
173 FEdge edge = (FEdge)it_edges.next();
174 TaskInfo taskinfo = taskinfos.get(edge.getTask().getSymbol());
175 double idouble = 0.0;
176 if(edge.getTaskExitIndex() >= taskinfo.m_exetime.length) {
179 tint = taskinfo.m_exetime[edge.getTaskExitIndex()];
180 idouble = taskinfo.m_probability[edge.getTaskExitIndex()];
182 edge.setExeTime(tint);
183 edge.setProbability(idouble);
184 if(taskinfo.m_byObj != -1) {
185 ((FlagState)edge.getSource()).setByObj(taskinfo.m_byObj);
196 randomProfileSetting();
200 private void checkBackEdge() {
201 // Indentify backedges
202 Iterator it_classes=state.getClassSymbolTable().getDescriptorsIterator();
203 while(it_classes.hasNext()) {
204 ClassDescriptor cd=(ClassDescriptor) it_classes.next();
206 Set<FlagState> fss = this.taskanalysis.getFlagStates(cd);
207 SCC scc=GraphNode.DFS.computeSCC(fss);
208 if (scc.hasCycles()) {
209 for(int i=0; i<scc.numSCC(); i++) {
210 if (scc.hasCycle(i)) {
211 Set cycleset = scc.getSCC(i);
212 Iterator it_fs = cycleset.iterator();
213 while(it_fs.hasNext()) {
214 FlagState fs = (FlagState)it_fs.next();
215 Iterator it_edges = fs.edges();
216 while(it_edges.hasNext()) {
217 FEdge edge = (FEdge)it_edges.next();
218 if(cycleset.contains(edge.getTarget())) {
220 edge.setisbackedge(true);
235 private void readProfileInfo(java.util.Hashtable<String, TaskInfo> taskinfos){
237 // read in profile data and set
238 //FileInputStream inStream = new FileInputStream("/scratch/profile.rst");
239 FileInputStream inStream =
240 new FileInputStream("/scratch/" + this.state.profilename);
241 byte[] b = new byte[1024 * 100];
242 int length = inStream.read(b);
244 System.out.print("No content in input file: /scratch/"
245 + this.state.profilename + "\n");
248 String profiledata = new String(b, 0, length);
250 // profile data format:
251 // taskname, numoftaskexits(; exetime, probability, numofnewobjtypes(,
252 // newobj type, num of objs)+)+
253 int inindex = profiledata.indexOf('\n');
254 while((inindex != -1) ) {
255 String inline = profiledata.substring(0, inindex);
256 profiledata = profiledata.substring(inindex + 1);
257 //System.printString(inline + "\n");
258 int tmpinindex = inline.indexOf(',');
259 if(tmpinindex == -1) {
262 String inname = inline.substring(0, tmpinindex);
263 String inint = inline.substring(tmpinindex + 1);
264 while(inint.startsWith(" ")) {
265 inint = inint.substring(1);
267 tmpinindex = inint.indexOf(',');
268 if(tmpinindex == -1) {
271 int numofexits = Integer.parseInt(inint.substring(0, tmpinindex));
272 TaskInfo tinfo = new TaskInfo(numofexits);
273 inint = inint.substring(tmpinindex + 1);
274 while(inint.startsWith(" ")) {
275 inint = inint.substring(1);
277 tmpinindex = inint.indexOf(';');
278 int byObj = Integer.parseInt(inint.substring(0, tmpinindex));
280 tinfo.m_byObj = byObj;
282 inint = inint.substring(tmpinindex + 1);
283 while(inint.startsWith(" ")) {
284 inint = inint.substring(1);
286 for(int i = 0; i < numofexits; i++) {
287 String tmpinfo = null;
288 if(i < numofexits - 1) {
289 tmpinindex = inint.indexOf(';');
290 tmpinfo = inint.substring(0, tmpinindex);
291 inint = inint.substring(tmpinindex + 1);
292 while(inint.startsWith(" ")) {
293 inint = inint.substring(1);
299 tmpinindex = tmpinfo.indexOf(',');
300 tinfo.m_exetime[i] = Long.parseLong(tmpinfo.substring(0, tmpinindex));
301 tmpinfo = tmpinfo.substring(tmpinindex + 1);
302 while(tmpinfo.startsWith(" ")) {
303 tmpinfo = tmpinfo.substring(1);
305 tmpinindex = tmpinfo.indexOf(',');
306 tinfo.m_probability[i] = Double.parseDouble(
307 tmpinfo.substring(0,tmpinindex));
308 tmpinfo = tmpinfo.substring(tmpinindex + 1);
309 while(tmpinfo.startsWith(" ")) {
310 tmpinfo = tmpinfo.substring(1);
312 tmpinindex = tmpinfo.indexOf(',');
314 if(tmpinindex == -1) {
315 numofnobjs = Integer.parseInt(tmpinfo);
316 if(numofnobjs != 0) {
317 System.err.println("Error profile data format!");
321 tinfo.m_newobjinfo.setElementAt(new Hashtable<String,Integer>(), i);
322 numofnobjs = Integer.parseInt(tmpinfo.substring(0, tmpinindex));
323 tmpinfo = tmpinfo.substring(tmpinindex + 1);
324 while(tmpinfo.startsWith(" ")) {
325 tmpinfo = tmpinfo.substring(1);
327 for(int j = 0; j < numofnobjs; j++) {
328 tmpinindex = tmpinfo.indexOf(',');
329 String nobjtype = tmpinfo.substring(0, tmpinindex);
330 tmpinfo = tmpinfo.substring(tmpinindex + 1);
331 while(tmpinfo.startsWith(" ")) {
332 tmpinfo = tmpinfo.substring(1);
335 if(j < numofnobjs - 1) {
336 tmpinindex = tmpinfo.indexOf(',');
337 objnum = Integer.parseInt(tmpinfo.substring(0, tmpinindex));
338 tmpinfo = tmpinfo.substring(tmpinindex + 1);
339 while(tmpinfo.startsWith(" ")) {
340 tmpinfo = tmpinfo.substring(1);
343 objnum = Integer.parseInt(tmpinfo);
345 tinfo.m_newobjinfo.elementAt(i).put(nobjtype, objnum);
349 taskinfos.put(inname, tinfo);
350 inindex = profiledata.indexOf('\n');
355 } catch(Exception e) {
361 private void randomProfileSetting() {
362 // Randomly set the newRate and probability of FEdges
363 java.util.Random r=new java.util.Random();
365 Iterator it_classes=state.getClassSymbolTable().getDescriptorsIterator();
366 for(; it_classes.hasNext();) {
367 ClassDescriptor cd=(ClassDescriptor) it_classes.next();
369 Vector rootnodes=this.taskanalysis.getRootNodes(cd);
370 if(rootnodes!=null) {
371 Iterator it_rootnodes=rootnodes.iterator();
372 for(; it_rootnodes.hasNext();) {
373 FlagState root=(FlagState)it_rootnodes.next();
374 Vector allocatingTasks = root.getAllocatingTasks();
375 if(allocatingTasks != null) {
376 for(int k = 0; k < allocatingTasks.size(); k++) {
377 TaskDescriptor td = (TaskDescriptor)allocatingTasks.elementAt(k);
379 (Vector<FEdge>)this.taskanalysis.getFEdgesFromTD(td);
380 int numEdges = fev.size();
382 for(int j = 0; j < numEdges; j++) {
383 FEdge pfe = fev.elementAt(j);
384 if(numEdges - j == 1) {
385 pfe.setProbability(total);
387 if((total != 0) && (total != 1)) {
389 tint = r.nextInt()%total;
392 pfe.setProbability(tint);
396 // tint = r.nextInt()%10;
397 // } while(tint <= 0);
398 //int newRate = tint;
399 //int newRate = (j+1)%2+1;
401 String cdname = cd.getSymbol();
402 if((cdname.equals("SeriesRunner")) ||
403 (cdname.equals("MDRunner")) ||
404 (cdname.equals("Stage")) ||
405 (cdname.equals("AppDemoRunner")) ||
406 (cdname.equals("FilterBankAtom")) ||
407 (cdname.equals("Grid")) ||
408 (cdname.equals("Fractal")) ||
409 (cdname.equals("KMeans")) ||
410 (cdname.equals("ZTransform")) ||
411 (cdname.equals("TestRunner")) ||
412 (cdname.equals("LinkList"))) {
413 newRate = this.coreNum;
414 } else if(cdname.equals("SentenceParser")) {
416 } else if(cdname.equals("BlurPiece")){
418 } else if(cdname.equals("ImageX")){
420 } else if(cdname.equals("ImageY")){
424 // tint = r.nextInt()%100;
425 // } while(tint <= 0);
426 // int probability = tint;
427 int probability = 100;
428 pfe.addNewObjInfo(cd, newRate, probability);
437 Iterator it_flags = this.taskanalysis.getFlagStates(cd).iterator();
438 while(it_flags.hasNext()) {
439 FlagState fs = (FlagState)it_flags.next();
440 Iterator it_edges = fs.edges();
442 while(it_edges.hasNext()) {
444 // tint = r.nextInt()%10;
445 // } while(tint <= 0);
447 FEdge edge = (FEdge)it_edges.next();
448 edge.setExeTime(tint);
449 if((fs.getClassDescriptor().getSymbol().equals("MD"))
450 && (edge.getTask().getSymbol().equals("t6"))) {
451 if(edge.isbackedge()) {
452 if(edge.getTarget().equals(edge.getSource())) {
453 edge.setProbability(93.75);
455 edge.setProbability(3.125);
458 edge.setProbability(3.125);
462 if(!it_edges.hasNext()) {
463 edge.setProbability(total);
465 if((total != 0) && (total != 1)) {
467 tint = r.nextInt()%total;
470 edge.setProbability(tint);
482 private ScheduleNode buildCFSTG(Vector<ScheduleEdge> toBreakDown,
483 Vector<TaskDescriptor> multiparamtds) {
484 Hashtable<ClassDescriptor, ClassNode> cdToCNodes =
485 new Hashtable<ClassDescriptor, ClassNode>();
486 // Build the combined flag transition diagram
487 // First, for each class create a ClassNode
488 Iterator it_classes = state.getClassSymbolTable().getDescriptorsIterator();
489 while(it_classes.hasNext()) {
490 ClassDescriptor cd = (ClassDescriptor) it_classes.next();
491 Set<FlagState> fStates = taskanalysis.getFlagStates(cd);
493 //Sort flagState nodes inside this ClassNode
494 Vector<FlagState> sFStates = FlagState.DFS.topology(fStates, null);
496 Vector rootnodes = taskanalysis.getRootNodes(cd);
497 if(((rootnodes != null) && (rootnodes.size() > 0))
498 || (cd.getSymbol().equals(TypeUtil.StartupClass))) {
499 ClassNode cNode = new ClassNode(cd, sFStates);
500 cNode.setSorted(true);
501 classNodes.add(cNode);
502 cd2ClassNode.put(cd, cNode);
503 cdToCNodes.put(cd, cNode);
512 ScheduleNode startupNode = null;
513 // For each ClassNode create a ScheduleNode containing it
515 for(i = 0; i < classNodes.size(); i++) {
516 ClassNode cn = classNodes.elementAt(i);
517 ScheduleNode sn = new ScheduleNode(cn, 0);
518 if(cn.getClassDescriptor().getSymbol().equals(TypeUtil.StartupClass)) {
521 cn.setScheduleNode(sn);
522 scheduleNodes.add(sn);
525 } catch (Exception e) {
530 // Create 'new' edges between the ScheduleNodes.
531 for(i = 0; i < classNodes.size(); i++) {
532 ClassNode cNode = classNodes.elementAt(i);
533 ClassDescriptor cd = cNode.getClassDescriptor();
534 Vector rootnodes = taskanalysis.getRootNodes(cd);
535 if(rootnodes != null) {
536 for(int h = 0; h < rootnodes.size(); h++) {
537 FlagState root=(FlagState)rootnodes.elementAt(h);
538 Vector allocatingTasks = root.getAllocatingTasks();
539 if(allocatingTasks != null) {
540 for(int k = 0; k < allocatingTasks.size(); k++) {
541 TaskDescriptor td = (TaskDescriptor)allocatingTasks.elementAt(k);
543 (Vector<FEdge>)taskanalysis.getFEdgesFromTD(td);
544 int numEdges = fev.size();
545 ScheduleNode sNode = cNode.getScheduleNode();
546 for(int j = 0; j < numEdges; j++) {
547 FEdge pfe = fev.elementAt(j);
548 FEdge.NewObjInfo noi = pfe.getNewObjInfo(cd);
549 if ((noi == null) || (noi.getNewRate() == 0)
550 || (noi.getProbability() == 0)) {
551 // fake creating edge, do not need to create corresponding
555 if(noi.getRoot() == null) {
556 // set root FlagState
559 FlagState pfs = (FlagState)pfe.getTarget();
560 ClassDescriptor pcd = pfs.getClassDescriptor();
561 ClassNode pcNode = cdToCNodes.get(pcd);
563 ScheduleEdge sEdge = new ScheduleEdge(sNode,
566 ScheduleEdge.NEWEDGE,
569 sEdge.setSourceCNode(pcNode);
570 sEdge.setTargetCNode(cNode);
571 sEdge.setTargetFState(root);
572 sEdge.setNewRate(noi.getNewRate());
573 sEdge.setProbability(noi.getProbability());
574 pcNode.getScheduleNode().addEdge(sEdge);
575 scheduleEdges.add(sEdge);
576 if((j !=0 ) || (k != 0) || (h != 0)) {
577 toBreakDown.add(sEdge);
582 allocatingTasks = null;
590 for(i = 0; i < multiparamtds.size(); i++) {
591 TaskDescriptor td = multiparamtds.elementAt(i);
592 ClassDescriptor cd = td.getParamType(0).getClassDesc();
593 // set the first parameter as main cd
594 // NOTE: programmer should write in such a style that
595 // for all multi-param tasks, the main class should be
596 // the first parameter
597 // TODO: may have bug when cd has multiple new flag states
598 this.td2maincd.put(td, cd);
604 private void treeTransform(Vector<ScheduleEdge> toBreakDown,
605 ScheduleNode startupNode) {
608 // Break down the 'cycle's
610 for(i = 0; i < toBreakDown.size(); i++ ) {
611 cloneSNodeList(toBreakDown.elementAt(i), false);
613 } catch (Exception e) {
618 // Remove fake 'new' edges
619 for(i = 0; i < scheduleEdges.size(); i++) {
620 ScheduleEdge se = (ScheduleEdge)scheduleEdges.elementAt(i);
621 if((0 == se.getNewRate()) || (0 == se.getProbability())) {
622 scheduleEdges.removeElement(se);
623 scheduleNodes.removeElement(se.getTarget());
627 // Do topology sort of the ClassNodes and ScheduleEdges.
628 Vector<ScheduleEdge> ssev = new Vector<ScheduleEdge>();
629 Vector<ScheduleNode> tempSNodes =
630 ClassNode.DFS.topology(scheduleNodes, ssev);
631 scheduleNodes.removeAllElements();
632 scheduleNodes = tempSNodes;
634 scheduleEdges.removeAllElements();
635 scheduleEdges = ssev;
639 // Set the cid of these ScheduleNode
640 Queue<ScheduleNode> toVisit = new LinkedList<ScheduleNode>();
641 toVisit.add(startupNode);
642 while(!toVisit.isEmpty()) {
643 ScheduleNode sn = toVisit.poll();
644 if(sn.getCid() == -1) {
645 // not visited before
646 sn.setCid(ScheduleNode.colorID++);
647 Iterator it_edge = sn.edges();
648 while(it_edge.hasNext()) {
649 toVisit.add((ScheduleNode)((ScheduleEdge)it_edge.next()).getTarget());
656 if(this.state.PRINTSCHEDULING) {
657 SchedulingUtil.printScheduleGraph(
658 this.state.outputdir + "scheduling_ori.dot", this.scheduleNodes);
662 private void handleDescenSEs(Vector<ScheduleEdge> ses) {
663 ScheduleEdge tempse = ses.elementAt(0);
664 long temptime = tempse.getListExeTime();
665 // find out the ScheduleEdge with least exeTime
666 for(int k = 1; k < ses.size(); k++) {
667 long ttemp = ses.elementAt(k).getListExeTime();
668 if(ttemp < temptime) {
669 tempse = ses.elementAt(k);
671 } // if(ttemp < temptime)
672 } // for(int k = 1; k < ses.size(); k++)
674 handleScheduleEdge(tempse, true);
675 ses.removeElement(tempse);
676 // handle other ScheduleEdges
677 for(int k = 0; k < ses.size(); k++) {
678 handleScheduleEdge(ses.elementAt(k), false);
679 } // for(int k = 0; k < ses.size(); k++)
682 private void CFSTGTransform() {
686 // table of all schedule edges associated to one fedge
687 Hashtable<FEdge, Vector<ScheduleEdge>> fe2ses =
688 new Hashtable<FEdge, Vector<ScheduleEdge>>();
689 // table of all fedges associated to one schedule node
690 Hashtable<ScheduleNode, Vector<FEdge>> sn2fes =
691 new Hashtable<ScheduleNode, Vector<FEdge>>();
692 ScheduleNode preSNode = null;
693 // Access the ScheduleEdges in reverse topology order
694 for(i = scheduleEdges.size(); i > 0; i--) {
695 ScheduleEdge se = (ScheduleEdge)scheduleEdges.elementAt(i-1);
696 if(ScheduleEdge.NEWEDGE == se.getType()) {
697 if(preSNode == null) {
698 preSNode = (ScheduleNode)se.getSource();
701 boolean split = false;
702 FEdge fe = se.getFEdge();
703 if(fe.getSource() == fe.getTarget()) {
704 // the associated start fe is a back edge
706 // check the number of newly created objs
707 int repeat = (int)Math.ceil(se.getNewRate()*se.getProbability()/100);
710 // more than one new objs, expand the new edge
711 for(int j = 1; j< repeat; j++ ) {
712 cloneSNodeList(se, true);
713 } // for(int j = 1; j< repeat; j++ )
715 se.setProbability(100);
716 } // if(repeat > 1)*/
718 // match the rates of obj creation and new obj consumption
719 rate = (int)Math.ceil(
720 se.getListExeTime()/calInExeTime(se.getSourceFState()));
721 } catch (Exception e) {
724 repeat = (rate > repeat)? rate : repeat;
725 // expand the new edge
726 for(int j = 1; j< repeat; j++ ) {
727 cloneSNodeList(se, true);
728 } // for(int j = 1; j< repeat; j++ )
730 se.setProbability(100);
731 /*for(int j = rate - 1; j > 0; j--) {
732 for(int k = repeat; k > 0; k--) {
733 cloneSNodeList(se, true);
734 } // for(int k = repeat; k > 0; k--)
735 } // for(int j = rate - 1; j > 0; j--)*/
736 } catch (Exception e) {
740 } else { // if(fe.getSource() == fe.getTarget())
741 // the associated start fe is not a back edge
742 // Note: if preSNode is not the same as se's source ScheduleNode
743 // handle any ScheduleEdges previously put into fe2ses whose source
744 // ScheduleNode is preSNode
745 boolean same = (preSNode == se.getSource());
747 // check the topology sort, only process those after se.getSource()
748 if(preSNode.getFinishingTime() < se.getSource().getFinishingTime()){
749 if(sn2fes.containsKey(preSNode)) {
750 Vector<FEdge> fes = sn2fes.remove(preSNode);
751 for(int j = 0; j < fes.size(); j++) {
752 FEdge tempfe = fes.elementAt(j);
753 Vector<ScheduleEdge> ses = fe2ses.get(tempfe);
754 this.handleDescenSEs(ses);
756 fe2ses.remove(tempfe);
757 } // for(int j = 0; j < fes.size(); j++)
761 preSNode = (ScheduleNode)se.getSource();
764 if(fe.getTarget().edges().hasNext()) {
765 // not associated with the last task, check if to split the snode
766 if((!(se.getTransTime() < this.transThreshold))
767 && (se.getSourceCNode().getTransTime() < se.getTransTime())) {
768 // it's better to transfer the other obj with preSnode
770 splitSNode(se, true);
772 } // if(!fe.getTarget().edges().hasNext())
775 // delay the expanding and merging until we find all such 'new'
776 // edges associated with a last task inside this ClassNode
777 if(fe2ses.get(fe) == null) {
778 fe2ses.put(fe, new Vector<ScheduleEdge>());
780 if(sn2fes.get((ScheduleNode)se.getSource()) == null) {
781 sn2fes.put((ScheduleNode)se.getSource(), new Vector<FEdge>());
783 if(!fe2ses.get(fe).contains(se)) {
784 fe2ses.get(fe).add(se);
786 if(!sn2fes.get((ScheduleNode)se.getSource()).contains(fe)) {
787 sn2fes.get((ScheduleNode)se.getSource()).add(fe);
790 } // if(fe.getSource() == fe.getTarget())
791 } // if(ScheduleEdge.NEWEDGE == se.getType())
792 } // for(i = scheduleEdges.size(); i > 0; i--)
793 if(!fe2ses.isEmpty()) {
794 Set<FEdge> keys = fe2ses.keySet();
795 Iterator it_keys = keys.iterator();
796 while(it_keys.hasNext()) {
797 FEdge tempfe = (FEdge)it_keys.next();
798 Vector<ScheduleEdge> ses = fe2ses.get(tempfe);
799 this.handleDescenSEs(ses);
810 if(this.state.PRINTSCHEDULING) {
811 SchedulingUtil.printScheduleGraph(
812 this.state.outputdir + "scheduling_extend.dot", this.scheduleNodes);
816 private void handleScheduleEdge(ScheduleEdge se,
820 int repeat = (int)Math.ceil(se.getNewRate() * se.getProbability() / 100);
823 if(se.getListExeTime() == 0) {
826 rate = (int)Math.ceil(
827 (se.getTransTime()-calInExeTime(se.getSourceFState()))
828 /se.getListExeTime());
833 } catch (Exception e) {
837 // clone the whole ScheduleNode lists starting with se's target
838 for(int j = 1; j < repeat; j++ ) {
839 cloneSNodeList(se, true);
842 se.setProbability(100);
846 // clone the whole ScheduleNode lists starting with se's target
847 for(int j = 0; j < repeat; j++ ) {
848 cloneSNodeList(se, true);
851 se.setProbability(100);
854 // merge the original ScheduleNode to the source ScheduleNode
855 ((ScheduleNode)se.getSource()).mergeSEdge(se);
856 scheduleNodes.remove(se.getTarget());
857 scheduleEdges.remove(se);
858 // As se has been changed into an internal edge inside a ScheduleNode,
859 // change the source and target of se from original ScheduleNodes
861 if(se.getType() == ScheduleEdge.NEWEDGE) {
862 se.setTarget(se.getTargetCNode());
863 //se.setSource(se.getSourceCNode());
864 //se.getTargetCNode().addEdge(se);
865 se.getSourceCNode().addEdge(se);
868 // clone the whole ScheduleNode lists starting with se's target
869 for(int j = 1; j < repeat; j++ ) {
870 cloneSNodeList(se, true);
873 se.setProbability(100);
875 } catch (Exception e) {
881 private void cloneSNodeList(ScheduleEdge sEdge,
882 boolean copyIE) throws Exception {
883 Hashtable<ClassNode, ClassNode> cn2cn =
884 new Hashtable<ClassNode, ClassNode>(); // hashtable from classnode in
885 // orignal se's targe to cloned one
886 ScheduleNode csNode =
887 (ScheduleNode)((ScheduleNode)sEdge.getTarget()).clone(cn2cn, 0);
888 scheduleNodes.add(csNode);
890 // Clone all the external in ScheduleEdges
893 Vector inedges = sEdge.getTarget().getInedgeVector();
894 for(i = 0; i < inedges.size(); i++) {
895 ScheduleEdge tse = (ScheduleEdge)inedges.elementAt(i);
897 switch(tse.getType()) {
898 case ScheduleEdge.NEWEDGE: {
899 se = new ScheduleEdge(csNode,"new",tse.getFstate(),tse.getType(),0);
900 se.setProbability(100);
905 case ScheduleEdge.TRANSEDGE: {
906 se = new ScheduleEdge(csNode,"transmit",tse.getFstate(),tse.getType(),0);
907 se.setProbability(tse.getProbability());
908 se.setNewRate(tse.getNewRate());
913 throw new Exception("Error: not valid ScheduleEdge here");
916 se.setSourceCNode(tse.getSourceCNode());
917 se.setTargetCNode(cn2cn.get(tse.getTargetCNode()));
918 se.setFEdge(tse.getFEdge());
919 se.setTargetFState(tse.getTargetFState());
921 tse.getSource().addEdge(se);
922 scheduleEdges.add(se);
926 sEdge.getTarget().removeInedge(sEdge);
927 sEdge.setTarget(csNode);
928 csNode.getInedgeVector().add(sEdge);
929 sEdge.setTargetCNode(cn2cn.get(sEdge.getTargetCNode()));
930 sEdge.setIsclone(true);
933 Queue<ScheduleNode> toClone = new LinkedList<ScheduleNode>(); // all nodes to be cloned
934 Queue<ScheduleNode> clone = new LinkedList<ScheduleNode>(); //clone nodes
935 Queue<Hashtable> qcn2cn = new LinkedList<Hashtable>(); // queue of the mappings of classnodes inside cloned ScheduleNode
936 Vector<ScheduleNode> origins = new Vector<ScheduleNode>(); // queue of source ScheduleNode cloned
937 Hashtable<ScheduleNode, ScheduleNode> sn2sn =
938 new Hashtable<ScheduleNode, ScheduleNode>(); // mapping from cloned ScheduleNode to clone ScheduleNode
940 toClone.add((ScheduleNode)sEdge.getTarget());
941 origins.addElement((ScheduleNode)sEdge.getTarget());
942 sn2sn.put((ScheduleNode)sEdge.getTarget(), csNode);
944 while(!toClone.isEmpty()) {
945 Hashtable<ClassNode, ClassNode> tocn2cn =
946 new Hashtable<ClassNode, ClassNode>();
947 csNode = clone.poll();
948 ScheduleNode osNode = toClone.poll();
949 cn2cn = qcn2cn.poll();
950 // Clone all the external ScheduleEdges and the following ScheduleNodes
951 Vector edges = osNode.getEdgeVector();
952 for(i = 0; i < edges.size(); i++) {
953 ScheduleEdge tse = (ScheduleEdge)edges.elementAt(i);
954 ScheduleNode tSNode =
955 (ScheduleNode)((ScheduleNode)tse.getTarget()).clone(tocn2cn, 0);
956 scheduleNodes.add(tSNode);
958 toClone.add((ScheduleNode)tse.getTarget());
959 origins.addElement((ScheduleNode)tse.getTarget());
960 sn2sn.put((ScheduleNode)tse.getTarget(), tSNode);
962 ScheduleEdge se = null;
963 switch(tse.getType()) {
964 case ScheduleEdge.NEWEDGE: {
965 se = new ScheduleEdge(tSNode,"new",tse.getFstate(),tse.getType(),0);
969 case ScheduleEdge.TRANSEDGE: {
970 se = new ScheduleEdge(tSNode,"transmit",tse.getFstate(),tse.getType(),0);
975 throw new Exception("Error: not valid ScheduleEdge here");
978 se.setSourceCNode(cn2cn.get(tse.getSourceCNode()));
979 se.setTargetCNode(tocn2cn.get(tse.getTargetCNode()));
980 se.setFEdge(tse.getFEdge());
981 se.setTargetFState(tse.getTargetFState());
982 se.setProbability(tse.getProbability());
983 se.setNewRate(tse.getNewRate());
986 scheduleEdges.add(se);
1001 private long calInExeTime(FlagState fs) throws Exception {
1003 ClassDescriptor cd = fs.getClassDescriptor();
1004 ClassNode cNode = cd2ClassNode.get(cd);
1005 exeTime = cNode.getFlagStates().elementAt(0).getExeTime() - fs.getExeTime();
1007 Vector inedges = cNode.getInedgeVector();
1008 // Now that there are associate ScheduleEdges, there may be
1009 // multiple inedges of a ClassNode
1010 if(inedges.size() > 1) {
1011 throw new Exception("Error: ClassNode's inedges more than one!");
1013 if(inedges.size() > 0) {
1014 ScheduleEdge sEdge = (ScheduleEdge)inedges.elementAt(0);
1015 cNode = (ClassNode)sEdge.getSource();
1016 exeTime += cNode.getFlagStates().elementAt(0).getExeTime();
1022 exeTime = cNode.getScheduleNode().getExeTime() - exeTime;
1026 private ScheduleNode splitSNode(ScheduleEdge se,
1028 assert(ScheduleEdge.NEWEDGE == se.getType());
1030 FEdge fe = se.getFEdge();
1031 FlagState fs = (FlagState)fe.getTarget();
1032 FlagState nfs = (FlagState)fs.clone();
1033 fs.getEdgeVector().removeAllElements();
1034 nfs.getInedgeVector().removeAllElements();
1035 ClassNode sCNode = se.getSourceCNode();
1037 // split the subtree whose root is nfs from the whole flag transition tree
1038 Vector<FlagState> sfss = sCNode.getFlagStates();
1039 Vector<FlagState> fStates = new Vector<FlagState>();
1040 Queue<FlagState> toiterate = new LinkedList<FlagState>();
1043 while(!toiterate.isEmpty()) {
1044 FlagState tfs = toiterate.poll();
1045 Iterator it_edges = tfs.edges();
1046 while(it_edges.hasNext()) {
1047 FlagState temp = (FlagState)((FEdge)it_edges.next()).getTarget();
1048 if(!fStates.contains(temp)) {
1050 toiterate.add(temp);
1051 sfss.removeElement(temp);
1057 Vector<FlagState> sFStates = FlagState.DFS.topology(fStates, null);
1059 // create a ClassNode and ScheduleNode for this subtree
1060 ClassNode cNode = new ClassNode(sCNode.getClassDescriptor(), sFStates);
1061 ScheduleNode sNode = new ScheduleNode(cNode, 0);
1062 cNode.setScheduleNode(sNode);
1063 cNode.setSorted(true);
1064 cNode.setTransTime(sCNode.getTransTime());
1065 classNodes.add(cNode);
1066 scheduleNodes.add(sNode);
1069 } catch (Exception e) {
1070 e.printStackTrace();
1072 // flush the exeTime of fs and its ancestors
1075 while(!toiterate.isEmpty()) {
1076 FlagState tfs = toiterate.poll();
1077 long ttime = tfs.getExeTime();
1078 Iterator it_inedges = tfs.inedges();
1079 while(it_inedges.hasNext()) {
1080 FEdge fEdge = (FEdge)it_inedges.next();
1081 FlagState temp = (FlagState)fEdge.getSource();
1082 long time = fEdge.getExeTime() + ttime;
1083 if(temp.getExeTime() > time) {
1084 temp.setExeTime(time);
1085 toiterate.add(temp);
1092 // create a 'trans' ScheudleEdge between this new ScheduleNode and se's
1093 // source ScheduleNode
1094 ScheduleEdge sEdge =
1095 new ScheduleEdge(sNode, "transmit", fs, ScheduleEdge.TRANSEDGE, 0);
1097 sEdge.setSourceCNode(sCNode);
1098 sEdge.setTargetCNode(cNode);
1099 sEdge.setTargetFState(nfs);
1101 // Add calculation codes for calculating transmit time of an object
1102 sEdge.setTransTime(cNode.getTransTime());
1103 se.getSource().addEdge(sEdge);
1104 scheduleEdges.add(sEdge);
1105 // remove the ClassNodes and internal ScheduleEdges out of this subtree
1106 // to the new ScheduleNode
1107 ScheduleNode oldSNode = (ScheduleNode)se.getSource();
1108 Iterator it_isEdges = oldSNode.getScheduleEdgesIterator();
1109 Vector<ScheduleEdge> toremove = new Vector<ScheduleEdge>();
1110 Vector<ClassNode> rCNodes = new Vector<ClassNode>();
1111 rCNodes.addElement(sCNode);
1112 if(it_isEdges != null) {
1113 while(it_isEdges.hasNext()) {
1114 ScheduleEdge tse = (ScheduleEdge)it_isEdges.next();
1115 if(rCNodes.contains(tse.getSourceCNode())) {
1116 if(sCNode.equals(tse.getSourceCNode())) {
1117 if (!(tse.getSourceFState().equals(fs))
1118 && (sFStates.contains(tse.getSourceFState()))) {
1119 tse.setSource(cNode);
1120 tse.setSourceCNode(cNode);
1125 sNode.getScheduleEdges().addElement(tse);
1126 sNode.getClassNodes().addElement(tse.getTargetCNode());
1127 rCNodes.addElement(tse.getTargetCNode());
1128 oldSNode.getClassNodes().removeElement(tse.getTargetCNode());
1129 toremove.addElement(tse);
1134 oldSNode.getScheduleEdges().removeAll(toremove);
1136 // redirect ScheudleEdges out of this subtree to the new ScheduleNode
1137 Iterator it_sEdges = se.getSource().edges();
1138 while(it_sEdges.hasNext()) {
1139 ScheduleEdge tse = (ScheduleEdge)it_sEdges.next();
1140 if(!(tse.equals(se)) && !(tse.equals(sEdge))
1141 && (tse.getSourceCNode().equals(sCNode))) {
1142 if(!(tse.getSourceFState().equals(fs))
1143 && (sFStates.contains(tse.getSourceFState()))) {
1144 tse.setSource(sNode);
1145 tse.setSourceCNode(cNode);
1146 sNode.getEdgeVector().addElement(tse);
1152 se.getSource().getEdgeVector().removeAll(toremove);
1159 //merge se into its source ScheduleNode
1160 sNode.setCid(((ScheduleNode)se.getSource()).getCid());
1161 ((ScheduleNode)se.getSource()).mergeSEdge(se);
1162 scheduleNodes.remove(se.getTarget());
1163 scheduleEdges.removeElement(se);
1164 // As se has been changed into an internal edge inside a ScheduleNode,
1165 // change the source and target of se from original ScheduleNodes
1167 if(se.getType() == ScheduleEdge.NEWEDGE) {
1168 se.setTarget(se.getTargetCNode());
1169 //se.setSource(se.getSourceCNode());
1170 //se.getTargetCNode().addEdge(se);
1171 se.getSourceCNode().addEdge(se);
1174 sNode.setCid(ScheduleNode.colorID++);
1175 handleScheduleEdge(se, true);
1177 } catch (Exception e) {
1178 e.printStackTrace();
1185 // TODO: restrict the number of generated scheduling according to the setted
1186 // scheduleThreshold
1187 private boolean coreMapping(int generateThreshold) throws Exception {
1188 if(this.coreNum == -1) {
1189 throw new Exception("Error: un-initialized coreNum when doing scheduling.");
1192 if(this.scheduleGraphs == null) {
1193 this.scheduleGraphs = new Vector<Vector<ScheduleNode>>();
1196 int reduceNum = this.scheduleNodes.size() - this.coreNum;
1198 // Combine some ScheduleNode if necessary
1199 // May generate multiple graphs suggesting candidate schedulings
1200 if(!(reduceNum > 0)) {
1201 // Enough cores, no need to combine any ScheduleNode
1202 this.scheduleGraphs.addElement(this.scheduleNodes);
1204 if(this.state.PRINTSCHEDULING) {
1205 String path = this.state.outputdir + "scheduling_" + gid + ".dot";
1206 SchedulingUtil.printScheduleGraph(path, this.scheduleNodes);
1210 SchedulingUtil.assignCids(this.scheduleNodes);
1212 // Go through all the Schedule Nodes, organize them in order of their cid
1213 Vector<Vector<ScheduleNode>> sNodeVecs =
1214 SchedulingUtil.rangeScheduleNodes(this.scheduleNodes);
1216 CombinationUtil.RootsGenerator rGen =
1217 CombinationUtil.allocateRootsGenerator(sNodeVecs,
1221 Random rand = new Random();
1222 boolean isBig = Math.pow(this.coreNum, reduceNum) > 1000;
1223 while((!isBig || (gid <= this.scheduleThreshold)) && (rGen.nextGen())) {
1224 // first get the chosen rootNodes
1225 Vector<Vector<ScheduleNode>> rootNodes = rGen.getRootNodes();
1226 Vector<Vector<ScheduleNode>> nodes2combine = rGen.getNode2Combine();
1228 CombinationUtil.CombineGenerator cGen =
1229 CombinationUtil.allocateCombineGenerator(rootNodes,
1231 while((!isBig || (gid <= this.scheduleThreshold)) && (cGen.nextGen())) {
1232 boolean implement = true;
1234 implement = Math.abs(rand.nextInt()) % 100 > generateThreshold;
1237 Vector<Vector<CombinationUtil.Combine>> combine = cGen.getCombine();
1238 Vector<ScheduleNode> sNodes =
1239 SchedulingUtil.generateScheduleGraph(this.state,
1245 this.scheduleGraphs.add(sNodes);
1252 nodes2combine = null;
1260 static class TaskInfo {
1261 public int m_numofexits;
1262 public long[] m_exetime;
1263 public double[] m_probability;
1264 public Vector<Hashtable<String, Integer>> m_newobjinfo;
1267 public TaskInfo(int numofexits) {
1268 this.m_numofexits = numofexits;
1269 this.m_exetime = new long[this.m_numofexits];
1270 this.m_probability = new double[this.m_numofexits];
1271 this.m_newobjinfo = new Vector<Hashtable<String, Integer>>();
1272 for(int i = 0; i < this.m_numofexits; i++) {
1273 this.m_newobjinfo.add(null);