// =================== GENERAL OUTPUT CONFIG =========================
const chartDisclaimers = {
Value: 'Value: Performance/(No_of_sockets * Price_of_CPU_dGPU), where prices are in USD as of December 2022.',
Efficiency: 'Efficiency: Performance/(No_of_sockets * TDP_of_CPU_dGPU), where total power dissipation (TDP) is in Watt as of December 2022.'
}
const OVdefaultSelections = {
platforms: {name: 'platform',
data: [
'Intel® Core™ i9-12900K CPU-only',
'Intel® Core™ i9-13900K CPU-only',
'Intel® Core™ i5-10500TE CPU-only',
'Intel® Core™ i5-13600K CPU-only',
'Intel® Core™ i5-8500 CPU-only',
'Intel® Core™ i7-8700T CPU-only',
'Intel® Core™ i9-10900TE CPU-only',
'Intel® Core™ i7-1165G7 CPU-only'
]
},
platformFilters: {name: 'coretype', data: ['CPU']},
models: {name: 'networkmodel',
data: [
'bert-large-uncased-whole-word-masking-squad-0001 ',
'mobilenet-ssd ',
'resnet-50',
'yolo_v3_tiny'
]
},
parameters: {name: 'kpi', data: ['Throughput']},
pracision: {name: 'precision', data: ['INT8', 'FP32']}
}
const OVMSdefaultSelections = {
platforms: {name: 'platform',
data: [
'Intel® Core™ i3-10100 CPU-only',
'Intel® Core™ i5-8500 CPU-only',
'Intel® Core™ i7-8700T CPU-only',
'Intel® Core™ i9-10920X CPU-only',
]
},
models: {name: 'networkmodel',
data: [
'bert-small-uncased-whole-word-masking-squad-0002',
'mobilenet-ssd ',
'resnet-50',
'yolo_v3_tiny'
]
},
parameters: {name: 'kpi', data: ['Throughput']},
pracision: {name: 'precision', data: ['OV-INT8 (reference)', 'INT8']}
}
// ====================================================
class Filter {
// param: GraphData[], networkModels[]
static FilterByNetworkModel(graphDataArr, networkModels) {
// This is a bit obtuse, collect all options from all models
// Some of them might return dupes, so convert them to a map, and get unique objects based on names
const optionMap = new Map();
networkModels.map((model) => graphDataArr.filter((graphData => graphData.networkModel === model)))
.flat(1)
.forEach(item => optionMap.set(item.platformName, item));
// convert the option map back to an array with just the values
return Array.from(optionMap.values());
}
// param: GraphData[], ieType
static FilterByIeType(graphDataArr, value) {
return graphDataArr.filter((data) => data.ieType.includes(value));
}
// param: GraphData[], clientPlatforms[]
static FilterByClientPlatforms(graphDataArr, platformsArr) {
return graphDataArr.filter((data) => platformsArr.includes(data.platformName));
}
// param: GraphData[], coreTypes[]
static FilterByCoreTypes(graphDataArr, coreTypes) {
if (coreTypes) {
return graphDataArr.filter((data) => coreTypes.includes(data.ieType));
}
return graphDataArr;
}
// param: GraphData[] (of one networkModel), key (throughput, latency, efficiency, value)
static getKpiData(graphDataArr, key) {
return graphDataArr.map((data) => {
return data[key];
});
}
}
class ExcelDataTransformer {
static transform(csvdata, version) {
const entries = csvdata.filter((entry) => {
return !entry.includes('begin_rec') && !entry.includes('end_rec');
});
// do other purging and data massaging here
// else generate
return entries.map((entry) => {
if (version == 'ovms')
return new GraphData(new OVMSExcelData(entry));
return new GraphData(new ExcelData(entry));
});
}
}
class ExcelData {
constructor(csvdataline) {
if (!csvdataline) {
return;
}
this.networkModel = csvdataline[0].toLowerCase();
this.release = csvdataline[1];
this.ieType = csvdataline[2];
this.platformName = csvdataline[3];
this.throughputInt8 = csvdataline[4];
this.throughputFP16 = csvdataline[5];
this.throughputFP32 = csvdataline[6];
this.value = csvdataline[7];
this.efficiency = csvdataline[8];
this.price = csvdataline[9];
this.tdp = csvdataline[10];
this.sockets = csvdataline[11];
this.pricePerSocket = csvdataline[12];
this.tdpPerSocket = csvdataline[13];
this.latency = csvdataline[14];
}
}
class OVMSExcelData extends ExcelData {
constructor(csvdataline) {
super(csvdataline);
this.throughputOVMSInt8 = csvdataline[5];
this.throughputInt8 = csvdataline[4];
this.throughputOVMSFP32 = csvdataline[7];
this.throughputFP32 = csvdataline[6];
}
}
class GraphData {
constructor(excelData) {
if (!excelData) {
return;
}
this.networkModel = excelData.networkModel;
this.release = excelData.release;
this.ieType = excelData.ieType;
this.platformName = excelData.platformName;
this.kpi = new KPI(
{
'ovmsint8': excelData.throughputOVMSInt8,
'ovmsfp32': excelData.throughputOVMSFP32,
'int8': excelData.throughputInt8,
'fp16': excelData.throughputFP16,
'fp32': excelData.throughputFP32
},
excelData.value,
excelData.efficiency,
excelData.latency);
this.price = excelData.price;
this.tdp = excelData.tdp;
this.sockets = excelData.sockets;
this.pricePerSocket = excelData.pricePerSocket;
this.tdpPerSocket = excelData.tdpPerSocket;
this.latency = excelData.latency;
}
}
class KPI {
constructor(precisions, value, efficiency, latency) {
this.throughput = precisions;
this.value = value;
this.efficiency = efficiency;
this.latency = latency;
}
}
class Modal {
static getIeTypeLabel(ietype) {
switch (ietype) {
case 'core':
return 'Client Platforms (Intel® Core™)';
case 'xeon':
return 'Server Platforms (Intel® Xeon®)';
case 'atom':
return 'Mobile Platforms (Intel® Atom™)';
case 'accel':
return 'Accelerator Platforms';
default:
return '';
}
}
static getCoreTypesLabels() {
return ['CPU', 'iGPU', 'CPU+iGPU'];
}
static getKpisLabels(version) {
if (version == 'ovms')
return ['Throughput'];
return ['Throughput', 'Value', 'Efficiency', 'Latency'];
}
static getPrecisionsLabels(version) {
if (version == 'ovms')
return ['OV-INT8 (reference)', 'INT8', 'OV-FP32 (reference)', 'FP32'];
return ['INT8', 'FP16', 'FP32'];
}
static getCoreTypes(labels) {
return labels.map((label) => {
switch (label) {
case 'CPU':
return 'core';
case 'iGPU':
return 'core-iGPU';
case 'CPU+iGPU':
return 'core-CPU+iGPU';
default:
return '';
}
});
}
static getPrecisions(labels) {
return labels.map((label) => {
switch (label) {
case 'OV-INT8 (reference)':
return 'ovmsint8';
case 'OV-FP32 (reference)':
return 'ovmsfp32';
case 'INT8':
return 'int8';
case 'FP16':
return 'fp16';
case 'FP32':
return 'fp32';
default:
return '';
}
});
}
}
class Graph {
constructor(data) {
this.data = data;
}
data = new GraphData();
// functions to get unique keys
static getNetworkModels(graphDataArr) {
return Array.from(new Set(graphDataArr.map((obj) => obj.networkModel)));
}
static getIeTypes(graphDataArr) {
return Array.from(new Set(graphDataArr.map((obj) => obj.ieType)));
}
static getPlatforms(graphDataArr) {
return Array.from(new Set(graphDataArr.map((obj) => obj.platformName)));
}
static getCoreTypes(graphDataArr) {
return Array.from(new Set(graphDataArr.map((obj) => obj.ieType)));
}
// param: GraphData[]
static getPlatformNames(graphDataArr) {
return graphDataArr.map((data) => data.platformName);
}
// param: GraphData[], kpi: string
static getDatabyKPI(graphDataArr, kpi) {
switch (kpi) {
case 'throughput':
return graphDataArr.map((data) => data.kpi.throughput);
case 'latency':
return graphDataArr.map((data) => data.kpi.latency);
case 'efficiency':
return graphDataArr.map((data) => data.kpi.efficiency);
case 'value':
return graphDataArr.map((data) => data.kpi.value);
default:
return [];
}
}
// this returns an object that is used to ender the chart
static getGraphConfig(kpi, precisions) {
switch (kpi) {
case 'throughput':
return {
chartTitle: 'Throughput',
chartSubtitle: '(higher is better)',
iconClass: 'throughput-icon',
datasets: precisions.map((precision) => this.getPrecisionConfig(precision)),
};
case 'latency':
return {
chartTitle: 'Latency',
chartSubtitle: '(lower is better)',
iconClass: 'latency-icon',
datasets: [{ data: null, color: '#8F5DA2', label: 'Milliseconds' }],
};
case 'value':
return {
chartTitle: 'Value',
chartSubtitle: '(higher is better)',
iconClass: 'value-icon',
datasets: [{ data: null, color: '#8BAE46', label: 'FPS/$ (INT8)' }],
};
case 'efficiency':
return {
chartTitle: 'Efficiency',
chartSubtitle: '(higher is better)',
iconClass: 'efficiency-icon',
datasets: [{ data: null, color: '#E96115', label: 'FPS/TDP (INT8)' }],
};
default:
return {};
}
}
static getPrecisionConfig(precision) {
switch (precision) {
case 'ovmsint8':
return { data: null, color: '#FF8F51', label: 'FPS (OV Ref. INT8)' };
case 'ovmsfp32':
return { data: null, color: '#B24501', label: 'FPS (OV Ref. FP32)' };
case 'int8':
return { data: null, color: '#00C7FD', label: 'FPS (INT8)' };
case 'fp16':
return { data: null, color: '#009fca', label: 'FPS (FP16)' };
case 'fp32':
return { data: null, color: '#007797', label: 'FPS (FP32)' };
default:
return {};
}
}
static getGraphPlatformText(platform) {
switch (platform) {
case 'atom':
return 'Mobile Platforms';
case 'core':
return 'Client Platforms';
case 'xeon':
return 'Server Platforms';
case 'accel':
return 'Accelerated Platforms';
default:
return '';
}
}
}
class ChartDisplay {
constructor(mode, numberOfCharts) {
this.mode = mode;
this.numberOfChartsInRow = numberOfCharts;
}
}
$(document).ready(function () {
$('.ov-toolkit-benchmark-results').on('click', () => showModal('ov'));
$('.ovms-toolkit-benchmark-results').on('click', () => showModal('ovms'));
function clickBuildGraphs(graph, networkModels, ietype, platforms, kpis, precisions) {
renderData(graph, networkModels, ietype, platforms, kpis, precisions);
$('.modal-footer').show();
$('#modal-display-graphs').show();
$('.edit-settings-btn').on('click', (event) => {
$('#modal-configure-graphs').show();
$('#modal-display-graphs').hide();
$('.modal-footer').hide();
$('.chart-placeholder').empty();
});
$('.graph-chart-title-header').on('click', (event) => {
var parent = event.target.parentElement;
if ($(parent).children('.chart-wrap,.empty-chart-container').is(":visible")) {
$(parent).children('.chart-wrap,.empty-chart-container').hide();
$(parent).children('.chevron-right-btn').show();
$(parent).children('.chevron-down-btn').hide();
$
} else {
$(parent).children('.chart-wrap,.empty-chart-container').show();
$(parent).children('.chevron-down-btn').show();
$(parent).children('.chevron-right-btn').hide();
}
});
}
function hideModal() {
$('#graphModal').remove();
$('body').css('overflow', 'auto');
}
function showModal(version) {
$('body').css('overflow', 'hidden');
let dataPath = '_static/benchmarks_files/OV-benchmark-data.csv';
if (version == 'ovms')
dataPath = '_static/benchmarks_files/OVMS-benchmark-data.csv';
Papa.parse(dataPath, {
download: true,
complete: (result) => renderModal(result, version)
});
}
function getSelectedNetworkModels() {
return $('.models-column-one input:checked, .models-column-two input:checked').not('[data-networkmodel="Select All"]').map(function () {
return $(this).data('networkmodel');
}).get();
}
function getSelectedIeType() {
return $('.ietype-column input:checked').map(function () {
return $(this).data('ietype');
}).get().pop();
}
function getSelectedCoreTypes() {
return $('.client-platform-column .selected').map(function () {
return $(this).data('coretype');
}).get();
}
function getSelectedClientPlatforms() {
return $('.client-platform-column input:checked').map(function () {
return $(this).data('platform');
}).get();
}
function getSelectedKpis() {
return $('.kpi-column input:checked').map(function () {
return $(this).data('kpi');
}).get();
}
function getSelectedPrecisions() {
return $('.precisions-column input:checked').map(function () {
return $(this).data('precision');
}).get();
}
function validateSelections() {
if (getSelectedNetworkModels().length > 0
&& getSelectedIeType()
&& getSelectedClientPlatforms().length > 0
&& getSelectedKpis().length > 0) {
if (getSelectedKpis().includes('Throughput')) {
if (getSelectedPrecisions().length > 0) {
$('#build-graphs-btn').prop('disabled', false);
return;
}
$('#build-graphs-btn').prop('disabled', true);
return;
}
$('#build-graphs-btn').prop('disabled', false);
return;
}
$('#build-graphs-btn').prop('disabled', true);
}
function renderModal(result, version) {
// remove header from csv line
result.data.shift();
var graph = new Graph(ExcelDataTransformer.transform(result.data, version));
var networkModels = Graph.getNetworkModels(graph.data);
var ieTypes = Graph.getIeTypes(graph.data);
fetch('_static/html/modal.html').then((response) => response.text()).then((text) => {
// generate and configure modal container
var modal = $('
');
modal.attr('id', 'graphModal');
modal.addClass('modal');
// generate and configure modal content from html import
var modalContent = $(text);
modalContent.attr('id', 'graphModalContent');
modalContent.addClass('modal-content');
modal.append(modalContent);
const models = networkModels.map((networkModel) => createCheckMark(networkModel, 'networkmodel'));
const selectAllModelsButton = createCheckMark('Select All', 'networkmodel')
modal.find('.models-column-one').append(selectAllModelsButton).append(models.slice(0, models.length / 2));
modal.find('.models-column-two').append(models.slice(models.length / 2));
const precisions = Modal.getPrecisionsLabels(version).map((precision) => createCheckMark(precision, 'precision'));
modal.find('.precisions-column').append(precisions);
selectAllCheckboxes(precisions);
disableAllCheckboxes(precisions);
const types = ieTypes.map((ieType) => {
var labelText = Modal.getIeTypeLabel(ieType);
if (labelText) {
const item = $('