Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 74 additions & 11 deletions src/projections/Tools/Overview/OverviewPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class OverviewPanel extends ScalePanel.Child
private int myRun = 0;

private int[][] entryData; // [pe][interval]
private int[] entriesPresent; // [ep] 1 if the EP appears in entryData

// idleData & mergedData (for supporting - utilization for now -
// the other two data formats)
Expand Down Expand Up @@ -377,29 +378,60 @@ protected void loadData(boolean saveImage) {
idleDataNormalized[i][j] = (byte) (100.0f * idleData[i][j]);
}
}
computeEntriesPresent();
// We default to coloring by entry method for log files
colorByEntry();
} else if (MainWindow.runObject[myRun].hasSumDetailData()) {
int intervalSize = (int) MainWindow.runObject[myRun].getSumDetailIntervalSize();
startInterval = (int) startTime / intervalSize;
startInterval = (int) (startTime / intervalSize);
endInterval = (int) Math.ceil(((double) endTime) / intervalSize) - 1;
int numIntervals = endInterval - startInterval + 1;

utilizationDataNormalized = new int[selectedPEs.size()][numIntervals];
idleDataNormalized = new byte[selectedPEs.size()][numIntervals];

MainWindow.runObject[myRun].LoadGraphData(intervalSize, startInterval, endInterval, false, selectedPEs);

utilizationDataNormalized = MainWindow.runObject[myRun].getSumDetailData_PE_interval();
idleDataNormalized = MainWindow.runObject[myRun].sumAnalyzer.getIdlePercentage();
double scale = 100.0 / intervalSize;
// Both of these are indexed by position in selectedPEs and are
// relative to startInterval, which is what this panel displays.
// systemUsageData[SYS_CPU] is already a 0-100 percentage.
utilizationDataNormalized = MainWindow.runObject[myRun].getSystemUsageData(1);
entryData = MainWindow.runObject[myRun].getSumDetailData_PE_interval_maxEP();

// idleDataNormalized is already in terms of percentage, so don't convert it
for (int i = 0; i < utilizationDataNormalized.length; i++) {
for (int j = 0; j < utilizationDataNormalized[i].length - 1; j++) {
utilizationDataNormalized[i][j] = (int) (scale * utilizationDataNormalized[i][j]);
// .sumd files carry no idle data, so idle has to come from the
// .sum files, which are indexed by absolute PE number and binned
// at their own interval size.
idleDataNormalized = new byte[selectedPEs.size()][numIntervals];
byte[][] sumIdle = (MainWindow.runObject[myRun].sumAnalyzer == null) ?
null : MainWindow.runObject[myRun].sumAnalyzer.getIdlePercentage();
long sumIntervalSize = MainWindow.runObject[myRun].getSummaryIntervalSize();
int pIdx = 0;
for (Integer pe : selectedPEs) {
for (int j = 0; j < numIntervals; j++) {
int idle = 0;
if (sumIdle != null && pe < sumIdle.length && sumIdle[pe] != null
&& sumIntervalSize > 0) {
int sumInterval = (int)
((long)(startInterval + j) * intervalSize / sumIntervalSize);
if (sumInterval < sumIdle[pe].length) {
idle = sumIdle[pe][sumInterval];
}
}
// The .sum idle and the .sumd per-EP times are accumulated by
// independent paths in charm's trace-summary and can overlap,
// so cap idle at whatever the entry methods leave free - the
// same reconciliation Time Profile and Usage Profile use.
int util = utilizationDataNormalized[pIdx][j];
idleDataNormalized[pIdx][j] =
(byte) Math.max(0, Math.min(idle, 100 - util));

// An interval with no recorded entry method time, or one the
// .sum file says was mostly idle, is drawn as idle rather than
// getting an entry method's color.
if (entryData[pIdx][j] < 0 || idleDataNormalized[pIdx][j] > util) {
entryData[pIdx][j] = numEPs + 1;
}
}
pIdx++;
}
computeEntriesPresent();
// Color by utilization for sumdetail
colorByUtil();
} else {
Expand All @@ -409,7 +441,38 @@ protected void loadData(boolean saveImage) {
}
}

/** Which entry methods actually appear in the image. The color chooser
* uses this so it offers only the colors on screen instead of every
* entry method in the run. Null if no entry method data was loaded. */
protected int[] getEntriesPresent() {
return entriesPresent;
}

/** Scanned once per load; ChooseEntriesWindow asks for the array
* repeatedly, and on a large trace entryData is millions of cells. */
private void computeEntriesPresent() {
if (entryData == null) {
entriesPresent = null;
return;
}
entriesPresent = new int[numEPs];
for (int p = 0; p < entryData.length; p++) {
if (entryData[p] == null)
continue;
for (int i = 0; i < entryData[p].length; i++) {
int ep = entryData[p][i];
if (ep >= 0 && ep < numEPs)
entriesPresent[ep] = 1;
}
}
}

protected void colorByEntry() {
if (entryData == null) {
// No per-entry-method data was loaded; stay in utilization mode
colorByUtil();
return;
}
mode = OverviewWindow.MODE_EP;
applyColorMap(entryData, true);
}
Expand Down
62 changes: 57 additions & 5 deletions src/projections/Tools/Overview/OverviewWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,18 @@
import projections.gui.ChooseEntriesWindow;
import projections.gui.ColorMap;
import projections.gui.ColorUpdateNotifier;
import projections.gui.EntryMethodVisibility;
import projections.gui.MainWindow;
import projections.gui.ProjectionsWindow;
import projections.gui.RangeDialog;
import projections.gui.ScalePanel;
import projections.gui.ScaleSlider;
import projections.gui.U;
import projections.gui.Util;

public class OverviewWindow extends ProjectionsWindow
implements MouseListener, ActionListener, ScalePanel.StatusDisplay, ColorUpdateNotifier
implements MouseListener, ActionListener, ScalePanel.StatusDisplay, ColorUpdateNotifier,
EntryMethodVisibility
{

// Temporary hardcode. This variable will be assigned appropriate
Expand All @@ -65,6 +68,10 @@ public class OverviewWindow extends ProjectionsWindow

private ColorMap utilColorMap;

/** Time at the left edge of the display; the panel's horizontal
* coordinates are microseconds relative to it */
private long displayStartTime;

private OverviewWindow thisWindow;


Expand Down Expand Up @@ -117,7 +124,16 @@ private void createLayout()
gbc.fill = GridBagConstraints.BOTH;
Util.gblAdd(windowPane, displayPanel, gbc, 0,0, 2,1, 2,1, 1,1,1,1);
scalePanel.setStatusDisplay(this);


// Timestamps under the horizontal tick ruler. The panel's horizontal
// coordinate is microseconds from the start of the displayed range,
// and getTicks() already follows pan and zoom.
scalePanel.setHorizontalAxisLabeler(new ScalePanel.AxisLabeler() {
public String label(double offset) {
return U.humanReadableString(displayStartTime + (long)offset, 3);
}
});


mChooseColors = new JButton("Choose Entry Method Colors");
mChooseColors.addActionListener(this);
Expand All @@ -126,7 +142,9 @@ private void createLayout()
radioPanel.setLayout(new GridBagLayout());
Util.gblAdd(radioPanel, new JLabel("Color By:"), gbc, 0,0, 1,1, 1,1);

if(MainWindow.runObject[myRun].hasLogFiles()){
// Both .log files and .sumd files carry per-entry-method data
if(MainWindow.runObject[myRun].hasLogFiles() ||
MainWindow.runObject[myRun].hasSumDetailData()){
colorByEntryMethod = new JRadioButton("Entry Method");
colorByEntryMethod.setSelected(true);
group.add(colorByEntryMethod);
Expand Down Expand Up @@ -172,6 +190,7 @@ private void createLayout()

private void setStlPanelData(long startTime, long endTime, SortedSet<Integer> pes){
double horSize, verSize;
displayStartTime = startTime;
if (pes == null) {
horSize=MainWindow.runObject[myRun].getTotalTime();
verSize=MainWindow.runObject[myRun].getNumProcessors();
Expand Down Expand Up @@ -256,10 +275,42 @@ public void actionPerformed(ActionEvent evt)
showDialog();
}
} else if (evt.getSource() == mChooseColors) {
new ChooseEntriesWindow(this);
new ChooseEntriesWindow(this, false, this);
}
}


/** Restrict "Choose Entry Method Colors" to the entry methods actually
* drawn (EntryMethodVisibility, consumed by ChooseEntriesWindow), and
* keep Idle and Overhead out of the list: this tool always draws them
* white and black, so picking colors for them would do nothing. */
public int[] getEntriesArray() {
return stl.getEntriesPresent();
}

public boolean hasEntryList() {
return stl.getEntriesPresent() != null;
}

public boolean handleIdleOverhead() {
return false;
}

public boolean entryIsVisibleID(Integer id) {
return true;
}

public void makeEntryVisibleID(Integer id) {
// visibility checkboxes are not shown for this tool's chooser
}

public void makeEntryInvisibleID(Integer id) {
}

public void displayMustBeRedrawn() {
repaint();
}

public void mouseClicked(MouseEvent evt) {
}

Expand All @@ -286,7 +337,8 @@ public void setStatus(String msg) {

/** Recieve notification that colors have been changed */
public void colorsHaveChanged(){
if (colorByEntryMethod.isSelected()){
// colorByEntryMethod does not exist for traces without entry method data
if (colorByEntryMethod != null && colorByEntryMethod.isSelected()){
stl.colorByEntry();
} else{
stl.colorByUtil();
Expand Down
3 changes: 3 additions & 0 deletions src/projections/analysis/Analysis.java
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ public int[][] getSumDetailData_PE_EP() {
public int[][] getSumDetailData_PE_interval() {
return intervalData.getSumDetailData_PE_interval();
}
public int[][] getSumDetailData_PE_interval_maxEP() {
return intervalData.getSumDetailData_PE_interval_maxEP();
}

public Color getEntryColor(int entryIdx) {
if (entryIdx == IDLE_ENTRY_POINT) {
Expand Down
16 changes: 16 additions & 0 deletions src/projections/analysis/IntervalData.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ public class IntervalData
private int sumDetailData_interval_EP[][] = null;
private int sumDetailData_PE_EP[][] = null;
private int sumDetailData_PE_interval[][] = null;
// [pe list index][interval] - which EP used the most time, or -1 for none.
// Indexed by position in the requested processor list, like systemUsageData.
private int sumDetailData_PE_interval_maxEP[][] = null;

/**
* The constructor
Expand Down Expand Up @@ -117,6 +120,7 @@ public void loadSumDetailIntervalData(long intervalSize, int intervalStart, int
sumDetailData_interval_EP = new int[numIntervals][numEPs];
sumDetailData_PE_EP = new int[numPEs][numEPs];
sumDetailData_PE_interval = new int[numPEs][numIntervals];
sumDetailData_PE_interval_maxEP = new int[processorList.size()][numIntervals];
systemUsageData = new int[3][processorList.size()][numIntervals];

int processorCount = 0;
Expand All @@ -139,12 +143,20 @@ public void loadSumDetailIntervalData(long intervalSize, int intervalStart, int

double[][] tempData = getData(curPe, TYPE_TIME, intervalSize, intervalStart, numIntervals);
for (int i = 0; i < numIntervals; i++) {
int maxEP = -1;
double maxEPTime = 0.0;
for (int ep = 0; ep < numEPs; ep++) {
sumDetailData_interval_EP[i][ep] += (int) tempData[ep][i];
sumDetailData_PE_EP[curPe][ep] += (int) tempData[ep][i];
sumDetailData_PE_interval[curPe][i] += (int) tempData[ep][i];
systemUsageData[1][processorCount][i] += (int) tempData[ep][i];
if (tempData[ep][i] > maxEPTime) {
maxEPTime = tempData[ep][i];
maxEP = ep;
}
}
// Overview colors each PE/interval cell by its dominant EP
sumDetailData_PE_interval_maxEP[processorCount][i] = maxEP;
// after accumulation for systemUsageData, convert to utilization percentage (0-100)
systemUsageData[1][processorCount][i] =
(int) IntervalUtils.timeToUtil(systemUsageData[1][processorCount][i], intervalSize);
Expand All @@ -166,6 +178,10 @@ public int[][] getSumDetailData_PE_interval() {
return sumDetailData_PE_interval;
}

public int[][] getSumDetailData_PE_interval_maxEP() {
return sumDetailData_PE_interval_maxEP;
}

public int[][][] getSystemUsageData() {
return systemUsageData;
}
Expand Down
19 changes: 17 additions & 2 deletions src/projections/gui/ChooseEntriesWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ public ChooseEntriesWindow(EntryMethodVisibility _data, boolean checkboxesVisibl

private void onlyEntryMethodsInRange() {
entryNames = new TreeMap<Integer, String>();
for (int i = 0; i < data.getEntriesArray().length; i++) {
if (MainWindow.runObject[myRun].getSts().getEntryNames().containsKey(i) && data.getEntriesArray()[i]!=0)
// asked for once: some tools scan their whole display to answer this
int[] entriesInRange = data.getEntriesArray();
for (int i = 0; i < entriesInRange.length; i++) {
if (MainWindow.runObject[myRun].getSts().getEntryNames().containsKey(i) && entriesInRange[i]!=0)
entryNames.put(i, MainWindow.runObject[myRun].getSts().getEntryNames().get(i) +
"::" +
MainWindow.runObject[myRun].getSts().entryChares.get(i));
Expand Down Expand Up @@ -207,6 +209,19 @@ else if (data!=null && data.hasEntryList())
p.add(topPanel, BorderLayout.NORTH);
p.add(scroller, BorderLayout.CENTER);

// Color choices take effect as they are made; this just dismisses
// the window, which otherwise has no obvious way to be closed.
JButton done = new JButton("Done");
done.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dispose();
}
});
JPanel donePanel = new JPanel();
donePanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
donePanel.add(done);
p.add(donePanel, BorderLayout.SOUTH);

this.setContentPane(p);

// Display it all
Expand Down
Loading
Loading