diff --git a/skyline-vscode/react-ui/src/App.js b/skyline-vscode/react-ui/src/App.js
index e4cfbd0..84c6858 100644
--- a/skyline-vscode/react-ui/src/App.js
+++ b/skyline-vscode/react-ui/src/App.js
@@ -1,23 +1,22 @@
-import './App.css';
-import './styles.css';
+import "./App.css";
+import "./styles.css";
-import React, { useState, useEffect } from 'react';
-import { Alert, Button, Card, Tab, Tabs, Container } from 'react-bootstrap';
+import React, { useState, useEffect } from "react";
+import { Alert, Button, Card, Tab, Tabs, Container } from "react-bootstrap";
-import ProjectInfo from './components/ProjectInfo'
-import Habitat from './sections/Habitat'
-import DeploymentTab from './sections/DeploymentTab'
-import WelcomeScreen from './sections/WelcomeScreen';
-import PerfBarContainer from './sections/PerfBarContainer';
+import ProjectInfo from "./components/ProjectInfo";
+import Habitat from "./sections/Habitat";
+import DeploymentTab from "./sections/DeploymentTab";
+import WelcomeScreen from "./sections/WelcomeScreen";
+import PerfBarContainer from "./sections/PerfBarContainer";
-import ReactTooltip from 'react-tooltip';
+import ReactTooltip from "react-tooltip";
-
-import { computePercentage, getTraceByLevel } from './utils/utils';
-import { profiling_data } from './data/mock_data';
-import EnergyConsumption from './sections/EnergyConsumption';
-import Iterations from './sections/Iterations';
-import MemThroughputContainer from './sections/MemThroughputContainer';
+import { computePercentage, getTraceByLevel } from "./utils/utils";
+import { profiling_data } from "./data/mock_data";
+import EnergyConsumption from "./sections/EnergyConsumption";
+import Iterations from "./sections/Iterations";
+import MemThroughputContainer from "./sections/MemThroughputContainer";
// https://stackoverflow.com/questions/54135313/webview-extension-in-typescript
/**
@@ -27,189 +26,212 @@ import MemThroughputContainer from './sections/MemThroughputContainer';
* @returns The VSCode API handle
*/
function acquireApi() {
- // if (typeof this.acquireApi.api == 'undefined') {
- if (typeof acquireApi.api === 'undefined') {
- if (typeof acquireVsCodeApi === "function") {
- let f = window['acquireVsCodeApi'];
- let a = f();
- acquireApi.api = a;
- } else {
- acquireApi.api = null;
- }
+ // if (typeof this.acquireApi.api == 'undefined') {
+ if (typeof acquireApi.api === "undefined") {
+ if (typeof acquireVsCodeApi === "function") {
+ let f = window["acquireVsCodeApi"];
+ let a = f();
+ acquireApi.api = a;
+ } else {
+ acquireApi.api = null;
}
+ }
- return acquireApi.api;
+ return acquireApi.api;
}
function restartProfiling() {
- console.log("restartProfiling");
- let vscode = App.vscodeApi;
- vscode.postMessage({
- command: "restart_profiling_clicked"
- });
+ console.log("restartProfiling");
+ let vscode = App.vscodeApi;
+ vscode.postMessage({
+ command: "restart_profiling_clicked",
+ });
}
const sendMock = false;
function App() {
- const [analysisState, setAnalysisState] = useState();
- const [textChanged, setTextChanged] = useState(false);
- const [timeBreakDown, setTimeBreakdown] = useState([]);
+ const [analysisState, setAnalysisState] = useState();
+ const [textChanged, setTextChanged] = useState(false);
+ const [timeBreakDown, setTimeBreakdown] = useState([]);
- const [vscodeApi, setVscodeApi] = useState(acquireApi());
- const [errorText, setErrorText] = useState();
- const [connectionStatus, setConnectionStatus] = useState(false);
- const [numIterations,setNumIterations] = useState(100000);
+ const [vscodeApi, setVscodeApi] = useState(acquireApi());
+ const [errorText, setErrorText] = useState();
+ const [connectionStatus, setConnectionStatus] = useState(false);
+ const [numIterations, setNumIterations] = useState(100000);
- App.vscodeApi = vscodeApi;
+ App.vscodeApi = vscodeApi;
- const resetApp = function() {
- setErrorText("");
- setAnalysisState(undefined);
- }
+ const resetApp = function () {
+ setErrorText("");
+ setAnalysisState(undefined);
+ };
- const connect = function() {
- resetApp();
- let vscode = App.vscodeApi;
- if(vscode){
- vscode.postMessage({
- command: "connect"
- });
- }
+ const connect = function () {
+ resetApp();
+ let vscode = App.vscodeApi;
+ if (vscode) {
+ vscode.postMessage({
+ command: "connect",
+ });
}
-
- const processAnalysisState = function (state) {
- setAnalysisState(state);
- if (state.breakdown) {
- let operation_tree = state.breakdown.operation_tree;
- let { coarse, fine } = getTraceByLevel(operation_tree);
- setTimeBreakdown({
- coarse: computePercentage(coarse, state.breakdown.iteration_run_time_ms),
- fine: computePercentage(fine, state.breakdown.iteration_run_time_ms)
- });
- ReactTooltip.rebuild();
- }
+ };
+
+ const processAnalysisState = function (state) {
+ setAnalysisState(state);
+ if (state.breakdown) {
+ let operation_tree = state.breakdown.operation_tree;
+ let { coarse, fine } = getTraceByLevel(operation_tree);
+ setTimeBreakdown({
+ coarse: computePercentage(
+ coarse,
+ state.breakdown.iteration_run_time_ms
+ ),
+ fine: computePercentage(fine, state.breakdown.iteration_run_time_ms),
+ });
+ ReactTooltip.rebuild();
}
+ };
+
+ useEffect(function () {
+ window.addEventListener("message", (event) => {
+ if (event.data["message_type"] === "connection") {
+ setConnectionStatus(event.data["status"]);
+ } else if (event.data["message_type"] === "analysis") {
+ processAnalysisState(event.data);
+ } else if (event.data["message_type"] === "text_change") {
+ setTextChanged(true);
+ } else if (event.data["message_type"] === "error") {
+ setErrorText(event.data["error_text"]);
+ }
+ });
- useEffect(function () {
- window.addEventListener('message', event => {
- if (event.data['message_type'] === "connection") {
- setConnectionStatus(event.data['status']);
- } else if (event.data['message_type'] === "analysis") {
- processAnalysisState(event.data);
- } else if (event.data['message_type'] === "text_change") {
- setTextChanged(true);
- } else if (event.data['message_type'] === 'error') {
- setErrorText(event.data['error_text']);
- }
- });
-
-
-
- if (sendMock) {
- setTimeout(() => {
- const mockResponse = profiling_data;
- processAnalysisState(mockResponse);
- }, 1000);
- }
-
- return() => {
- window.removeEventListener("message",()=>{}) //remove event listener before re-render to avoid memory leaks
- }
- }, []);
-
- if (!connectionStatus && !sendMock) {
- return (
- <>
-
- Connection Error
-
- Connection has been lost to the profiler. Please reconnect the profiler and double check your ports then click connect
-
- Reconnect
-
- >
- )
- }
- if (errorText) {
- return (
- <>
-
- Analysis Error
-
- An error has occurred during analysis. This could be a problem with Skyline or possibly your code. For more information, refer to the detailed message below:
-
-
-
-
- {errorText}
-
-
-
- Restart Profiling
-
- >
- )
- }
- else if (analysisState && analysisState['throughput'] && Object.keys(analysisState['throughput']).length > 0)
- {
- return (
- <>
-
-
- Project Information
-
-
- { textChanged &&
-
- Change is detected in the project. Restart Profiling
-
- }
-
-
-
-
-
-
-
-
-
{
- return {
- label: elem["percentage"] > 10 ? elem["name"] : "",
- percentage: elem["percentage"],
- clickable: false
- }
- }) : []}
- renderPerfBars={timeBreakDown.fine}
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
- }
- else {
- return (
- <>
-
- >
- );
+ if (sendMock) {
+ setTimeout(() => {
+ const mockResponse = profiling_data;
+ processAnalysisState(mockResponse);
+ }, 1000);
}
+
+ return () => {
+ window.removeEventListener("message", () => {}); //remove event listener before re-render to avoid memory leaks
+ };
+ }, []);
+
+ if (!connectionStatus && !sendMock) {
+ return (
+ <>
+
+ Connection Error
+
+ Connection has been lost to the profiler. Please reconnect the
+ profiler and double check your ports then click connect
+
+ Reconnect
+
+ >
+ );
+ }
+ if (errorText) {
+ return (
+ <>
+
+ Analysis Error
+
+ An error has occurred during analysis. This could be a problem with
+ Skyline or possibly your code. For more information, refer to the
+ detailed message below:
+
+
+
+ {errorText}
+
+
+ Restart Profiling
+
+ >
+ );
+ } else if (
+ analysisState &&
+ analysisState["throughput"] &&
+ Object.keys(analysisState["throughput"]).length > 0
+ ) {
+ return (
+ <>
+
+
+ Project Information
+
+
+ {textChanged && (
+
+ Change is detected in the project.{" "}
+
+ Restart Profiling
+
+
+ )}
+
+
+
+
+
+
+
+
+
{
+ return {
+ label:
+ elem["percentage"] > 10 ? elem["name"] : "",
+ percentage: elem["percentage"],
+ clickable: false,
+ };
+ })
+ : []
+ }
+ renderPerfBars={timeBreakDown.fine}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ } else {
+ return (
+ <>
+
+ >
+ );
+ }
}
export default App;
diff --git a/skyline-vscode/react-ui/src/components/BarGraph.js b/skyline-vscode/react-ui/src/components/BarGraph.js
new file mode 100644
index 0000000..e9c3bca
--- /dev/null
+++ b/skyline-vscode/react-ui/src/components/BarGraph.js
@@ -0,0 +1,49 @@
+import React from "react";
+import {
+ ResponsiveContainer,
+ BarChart,
+ XAxis,
+ YAxis,
+ Tooltip,
+ Bar,
+ Label,
+} from "recharts";
+
+export const HorizontalBarGraph = ({ data, height, xlabel, ylabel, color }) => {
+ let upperLimit = 0;
+ data.forEach((element) => {
+ const predictedTime = parseFloat(Number(element.x));
+ upperLimit = predictedTime > upperLimit ? predictedTime : upperLimit;
+ });
+ upperLimit *= 1.1;
+ data.sort((a, b) => a.x - b.x);
+ return (
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/skyline-vscode/react-ui/src/components/HorizontalBarGraph.js b/skyline-vscode/react-ui/src/components/HorizontalBarGraph.js
deleted file mode 100644
index 23176c5..0000000
--- a/skyline-vscode/react-ui/src/components/HorizontalBarGraph.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from "react";
-import {
- ResponsiveContainer,
- BarChart,
- CartesianGrid,
- XAxis,
- YAxis,
- Tooltip,
- Bar,
-} from "recharts";
-
-const BarGraph = ({ data, height, xlabel, ylabel, color }) => {
- let upperLimit = 0;
- data.forEach(element => {
- const predictedTime = parseFloat(Number(element.x));
- upperLimit = predictedTime > upperLimit ? predictedTime: upperLimit
- });
- upperLimit *=1.1;
- return (
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default BarGraph;
diff --git a/skyline-vscode/react-ui/src/components/ScatterGraph.js b/skyline-vscode/react-ui/src/components/ScatterGraph.js
index 48658d4..b592e36 100644
--- a/skyline-vscode/react-ui/src/components/ScatterGraph.js
+++ b/skyline-vscode/react-ui/src/components/ScatterGraph.js
@@ -9,23 +9,33 @@ import {
ResponsiveContainer,
Label,
Legend,
+ Tooltip,
+ LabelList,
} from "recharts";
-import { calculate_training_time,currencyFormat } from "../utils/utils";
+import { calculate_training_time, currencyFormat } from "../utils/utils";
+import { gpuPropertyList } from "../data/providers";
-const ScatterGraph = ({ data, onClickHandler, xlabel, ylabel, providers,numIterations }) => {
+export const ProviderScatterGraph = ({
+ data,
+ onClickHandler,
+ xlabel,
+ ylabel,
+ providers,
+ numIterations,
+}) => {
const finalData = [];
- if (data.length>0){
- data.forEach((item)=>{
+ if (data.length > 0) {
+ data.forEach((item) => {
const time = calculate_training_time(numIterations, item);
const cost = item.info.cost * time;
finalData.push({
...item,
x: time,
- y: cost
- })
- })
+ y: cost,
+ });
+ });
}
-
+
const formatYAxis = (value) => {
return currencyFormat(value);
};
@@ -33,9 +43,9 @@ const ScatterGraph = ({ data, onClickHandler, xlabel, ylabel, providers,numItera
const fortmatXAxis = (value) => {
const formatter = new Intl.NumberFormat("en-US", {
notation: "compact",
- })
+ });
return formatter.format(value);
- }
+ };
return (
<>
@@ -94,4 +104,147 @@ const ScatterGraph = ({ data, onClickHandler, xlabel, ylabel, providers,numItera
);
};
-export default ScatterGraph;
+export const HabitatScatterGraph = ({ habitatData, height }) => {
+ const renderTooltip = (props) => {
+ const { active, payload } = props;
+
+ if (active && payload && payload.length) {
+ const data = payload[0] && payload[0].payload;
+
+ return (
+
+
{data.card}
+
+ time:
+ {data.time}
+
+
+ );
+ }
+
+ return null;
+ };
+
+ const renderCustomizedLabel = (props) => {
+ const { x, y, width, height, value } = props;
+ console.log(x, y, width, height, value);
+ const y_offset = 5;
+ return (
+
+ {value}
+
+ );
+ };
+
+ const NUMBER_OF_COLUMNS = 5;
+ const habitatConsumerCards = [];
+ const habitatServerCards = [];
+ const sourceInHabitat = [];
+
+ habitatData.sort((a, b) => a[1] - b[1]);
+
+ habitatData.forEach((habitatItem,idx) => {
+ const findGPUProperty = gpuPropertyList.find(
+ (item) => item.name.toLowerCase() === habitatItem[0].toLowerCase()
+ );
+ if (findGPUProperty) {
+ if (findGPUProperty.type === "server") {
+ habitatServerCards.push({
+ time: parseFloat(Number(habitatItem[1]).toFixed(2)),
+ card: habitatItem[0],
+ index: idx%NUMBER_OF_COLUMNS +0.5,
+ size: 100,
+ });
+ } else {
+ habitatConsumerCards.push({
+ time: parseFloat(Number(habitatItem[1]).toFixed(2)),
+ card: habitatItem[0],
+ index: idx%NUMBER_OF_COLUMNS+0.5,
+ size: 100,
+ });
+ }
+ } else {
+ sourceInHabitat.push({
+ time: parseFloat(Number(habitatItem[1]).toFixed(2)),
+ card: "Local GPU",
+ index: idx%NUMBER_OF_COLUMNS+0.5,
+ size: 100,
+ });
+ }
+ });
+ console.log(sourceInHabitat)
+
+ const UPPER_LIMIT =
+ 1.2 * habitatData.reduce((a, b) => Math.max(a, b[1]), -Infinity);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/skyline-vscode/react-ui/src/data/mock_data.js b/skyline-vscode/react-ui/src/data/mock_data.js
index 57d6147..7faef0f 100644
--- a/skyline-vscode/react-ui/src/data/mock_data.js
+++ b/skyline-vscode/react-ui/src/data/mock_data.js
@@ -873,18 +873,18 @@ export const profiling_data = {
],
},
habitat: [
- ["source", 22.029312],
- ["P100",14.069682],
- ["P4000", 127.268085], // 27.268085
- ["RTX2070", 16.088268],
- ["RTX2080Ti", 11.826558],
- ["T4", 22.029312],
- ["V100", 10.182922],
- ["A100", 10.068596],
- ["RTX3090", 9.841998],
- ["A40", 11.558072],
- ["A4000", 14.67059],
- ["RTX4000", 20.2342],
+ ["source", 21.767504],
+ ["P100",13.972405],
+ ["P4000", 56.889559], // 27.268085
+ ["RTX2070", 15.942612],
+ ["RTX2080Ti", 11.753607],
+ ["T4", 21.767504],
+ ["V100", 10.154535],
+ ["A100", 10.081459],
+ ["RTX3090", 9.823705],
+ ["A40", 11.507118],
+ ["A4000", 14.537657],
+ ["RTX4000", 20.04405],
],
energy: {
current: {
diff --git a/skyline-vscode/react-ui/src/data/providers.js b/skyline-vscode/react-ui/src/data/providers.js
index cb3dbed..d216603 100644
--- a/skyline-vscode/react-ui/src/data/providers.js
+++ b/skyline-vscode/react-ui/src/data/providers.js
@@ -269,15 +269,15 @@ export const cloudProviders = {
}
export const gpuPropertyList = [
- { name: "p100", vmem: 16 },
- { name: "p4000", vmem: 8 },
- { name: "rtx2070", vmem: 8 },
- { name: "rtx2080ti", vmem: 11 },
- { name: "t4", vmem: 16 },
- { name: "v100", vmem: 16 },
- { name: "a100", vmem: 40 },
- { name: "rtx3090", vmem: 24},
- { name: "a40", vmem: 48},
- { name: "a4000", vmem: 16},
- { name: "rtx4000", vmem: 8}
+ { name: "p100", vmem: 16, type: "server" },
+ { name: "p4000", vmem: 8, type: "server" },
+ { name: "rtx2070", vmem: 8, type: "consumer" },
+ { name: "rtx2080ti", vmem: 11, type: "consumer" },
+ { name: "t4", vmem: 16, type: "server" },
+ { name: "v100", vmem: 16, type: "server" },
+ { name: "a100", vmem: 40, type: "server" },
+ { name: "rtx3090", vmem: 24, type: "consumer" },
+ { name: "a40", vmem: 48, type: "server" },
+ { name: "a4000", vmem: 16, type: "server" },
+ { name: "rtx4000", vmem: 8, type: "consumer" }
];
diff --git a/skyline-vscode/react-ui/src/sections/Habitat.js b/skyline-vscode/react-ui/src/sections/Habitat.js
index 2c9ff37..3e15f12 100644
--- a/skyline-vscode/react-ui/src/sections/Habitat.js
+++ b/skyline-vscode/react-ui/src/sections/Habitat.js
@@ -1,60 +1,36 @@
+import React from "react";
+
import Subheader from "../components/Subheader";
-import { Container, Row, Spinner, Card } from "react-bootstrap";
-import BarGraph from "../components/HorizontalBarGraph";
+import { Container, Row,Spinner, Card } from "react-bootstrap";
+import { HabitatScatterGraph } from "../components/ScatterGraph";
export default function Habitat({ habitatData }) {
- // The colors used for the visualization
- // The first n-1 colors should follow a blue gradient while the last
- // color is used for the current device.
- const colors = [
- "#7986cb",
- "#5c6bc0",
- "#3f51b5",
- "#3949ab",
- "#303f9f",
- "#283593",
- "#1a237e",
- "#ffc300",
- ];
-
- let habitatProperties = [];
-
- for (var i = 0; i < habitatData.length; i++) {
- habitatProperties.push({
- y: habitatData[i][0],
- x: habitatData[i][1].toFixed(2),
- fill:
- habitatData[i][0] === "source"
- ? colors[colors.length - 1]
- : colors[i % (colors.length - 1)],
- });
- }
return (
-
-
Habitat
-
- {habitatData.length === 0 && (
-
-
-
-
- Loading Habitat
- predictions.
-
-
-
-
- )}
- {habitatData !== [] && (
-
- )}
+ <>
+
+
Habitat
+
+ {habitatData.length === 0 ? (
+
+
+
+
+ Loading Habitat
+ predictions.
+
+
+
+
+ ):
+ (
+
+ )}
+
-
+ >
);
}
diff --git a/skyline-vscode/react-ui/src/sections/Iterations.js b/skyline-vscode/react-ui/src/sections/Iterations.js
index 0018160..ad4f1ed 100644
--- a/skyline-vscode/react-ui/src/sections/Iterations.js
+++ b/skyline-vscode/react-ui/src/sections/Iterations.js
@@ -1,5 +1,5 @@
import React, { useState } from "react";
-import { Button, Form, FloatingLabel } from "react-bootstrap";
+import { Row, Col, Button, Form, FloatingLabel } from "react-bootstrap";
import styled from "styled-components";
import { numberFormat } from "../utils/utils";
@@ -15,13 +15,13 @@ const Iterations = ({ setNumIterations }) => {
const name = e.target.name;
let value = e.target.value;
if (!value) {
- setIterations((prevState)=>({ ...prevState, [name]: 0 }));
+ setIterations((prevState) => ({ ...prevState, [name]: 0 }));
return;
}
const val = parseFloat(value);
if (Number.isInteger(val)) {
- setIterations((prevState)=>({ ...prevState, [name]: val }));
+ setIterations((prevState) => ({ ...prevState, [name]: val }));
setMessage(null);
} else {
setMessage("You must only use integer numbers");
@@ -36,14 +36,15 @@ const Iterations = ({ setNumIterations }) => {
iterations.iterPerEpoch &&
Number.isInteger(iterations.iterPerEpoch)
) {
- if(iterations.epochs * iterations.iterPerEpoch>=1e21){
- setMessage("The total number of iterations should be less than 1e21");
- }
- else{
+ if (iterations.epochs * iterations.iterPerEpoch >= 1e21) {
+ setMessage("The total number of iterations should be less than 1e21");
+ } else {
setEstimation(true);
setNumIterations(iterations.epochs * iterations.iterPerEpoch);
setMessage(null);
- setTimeout(()=>{setEstimation(false)},2000);
+ setTimeout(() => {
+ setEstimation(false);
+ }, 2000);
}
}
};
@@ -51,63 +52,80 @@ const Iterations = ({ setNumIterations }) => {
return (
<>
-
-
-
- {message}
-
- )}
-
-
- Total number of iterations:{" "}
- {numberFormat(iterations.epochs * iterations.iterPerEpoch)}
-
-
-
-
- {estimation ? 'processing':'submit'}
-
-
-
+
-
>
);
};
const Wrapper = styled.main`
- .warning-message{
+ .warning-message {
font-size: 14;
font-weight: 700;
color: "red";
-
}
- .iterations-text{
+ .iterations-text {
font-size: 14;
font-weight: 700;
}
diff --git a/skyline-vscode/react-ui/src/sections/ProviderPanel.js b/skyline-vscode/react-ui/src/sections/ProviderPanel.js
index c868e42..cdb138b 100644
--- a/skyline-vscode/react-ui/src/sections/ProviderPanel.js
+++ b/skyline-vscode/react-ui/src/sections/ProviderPanel.js
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react";
import Subheader from "../components/Subheader";
-import ScatterGraph from "../components/ScatterGraph";
+import {ProviderScatterGraph} from "../components/ScatterGraph";
import {
Badge,
ButtonGroup,
@@ -243,7 +243,7 @@ const ProviderPanel = ({ numIterations, habitatData }) => {
-