From 2fa6fcbe3f3c581c833b0b814791df104c4e2aa1 Mon Sep 17 00:00:00 2001 From: David Blundell Date: Thu, 16 Jan 2025 13:18:04 -0500 Subject: [PATCH 01/22] Update styleguide with tag component --- src/routes/Styleguide.tsx | 36 ++++++++++++++++++++++++++++++++++++ src/scss/_blueprintjs.scss | 31 ++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/src/routes/Styleguide.tsx b/src/routes/Styleguide.tsx index cdc8938a..cec11252 100644 --- a/src/routes/Styleguide.tsx +++ b/src/routes/Styleguide.tsx @@ -11,6 +11,7 @@ import { Intent, PopoverPosition, Switch, + Tag, Tooltip, } from '@blueprintjs/core'; import { IconNames } from '@blueprintjs/icons'; @@ -407,6 +408,41 @@ export default function Styleguide() {

Components

+

Tags

+ +
+ + None + + + Primary + + + Warning + + + Success + + + Danger + +
+

Progress bar

diff --git a/src/scss/_blueprintjs.scss b/src/scss/_blueprintjs.scss index a62aaf0a..26aa6172 100644 --- a/src/scss/_blueprintjs.scss +++ b/src/scss/_blueprintjs.scss @@ -61,7 +61,36 @@ $dark-danger-background-base: $tt-red-accent; 'warning': $dark-warning-background-base, 'danger': $tt-red, ), - $dark-navbar-background-color: transparent + $pt-text-color: $tt-grey-2, + $dark-navbar-background-color: transparent, + // Background/Hover/Active/Text colours + $tag-intent-colors: + ( + 'primary': ( + $dark-primary-background-base, + color.adjust($dark-primary-background-base, $lightness: -10%), + color.adjust($dark-primary-background-base, $lightness: -5%), + $white, + ), + 'success': ( + $green3, + $green2, + $green1, + $white, + ), + 'warning': ( + $dark-warning-background-base, + color.adjust($dark-warning-background-base, $lightness: -10%), + color.adjust($dark-warning-background-base, $lightness: -5%), + $tt-grey-2, + ), + 'danger': ( + $dark-danger-background-base, + $red2, + $red1, + $white, + ), + ) ); // Overrides for BlueprintJS which cannot be done via SASS variables From 93a296e64014d518a8f600cfee823dcf83ba70f3 Mon Sep 17 00:00:00 2001 From: Denis Kartashevskiy Date: Thu, 16 Jan 2025 13:54:21 -0500 Subject: [PATCH 02/22] bind perf data. render perf on device list --- src/components/OperationList.tsx | 29 ++++++++++++++++-- src/definitions/PerfTable.ts | 1 + src/functions/math.ts | 4 +-- src/hooks/useAPI.tsx | 50 +++++++++++++++++++++++++++++++- 4 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/components/OperationList.tsx b/src/components/OperationList.tsx index 4d0d850b..801afb64 100644 --- a/src/components/OperationList.tsx +++ b/src/components/OperationList.tsx @@ -14,11 +14,12 @@ import Collapsible from './Collapsible'; import OperationArguments from './OperationArguments'; import LoadingSpinner from './LoadingSpinner'; import 'styles/components/ListView.scss'; -import { useOperationsList } from '../hooks/useAPI'; +import { DeviceOperationMapping, useGetDeviceOperationListPerf, useOperationsList } from '../hooks/useAPI'; import ROUTES from '../definitions/routes'; import { expandedOperationsAtom, shouldCollapseAllOperationsAtom } from '../store/app'; import { OperationDescription } from '../model/APIData'; import ListItem from './ListItem'; +import { formatSize } from '../functions/math'; const PLACEHOLDER_ARRAY_SIZE = 10; const OPERATION_EL_HEIGHT = 39; // Height in px of each list item @@ -34,6 +35,7 @@ const OperationList = () => { const location = useLocation(); const navigate = useNavigate(); const { data: fetchedOperations, error, isLoading } = useOperationsList(); + const perfData = useGetDeviceOperationListPerf(); const scrollElementRef = useRef(null); const [filterQuery, setFilterQuery] = useState(''); @@ -125,7 +127,9 @@ const OperationList = () => { setFilteredOperationsList(operations); } - }, [fetchedOperations, filterQuery, shouldSortByID, shouldSortDuration]); + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [fetchedOperations, filterQuery, shouldSortByID, shouldSortDuration, perfData]); useEffect(() => { const initialOperationId = location.state?.previousOperationId; @@ -309,6 +313,26 @@ const OperationList = () => {

Python execution time: {operation.duration}s

+

+ {perfData + ?.filter( + (perf: DeviceOperationMapping) => perf.id === operation.id, + ) + .map((perf) => ( +

+ {perf.perfData?.['OP CODE']} device + time:{' '} + {formatSize( + Number( + perf.perfData?.['DEVICE KERNEL DURATION [ns]'], + ) / 1000, + + 0, + )}{' '} + µs +

+ ))} +

{operation.arguments && ( { ); }; + function getOperationFilterName(operation: OperationDescription) { return `${operation.id} ${operation.name} (${operation.operationFileIdentifier}) `; } diff --git a/src/definitions/PerfTable.ts b/src/definitions/PerfTable.ts index 87ba83fc..4b816f09 100644 --- a/src/definitions/PerfTable.ts +++ b/src/definitions/PerfTable.ts @@ -15,6 +15,7 @@ export interface Cell { } export interface RowData { + ID: number; 'DEVICE ID'?: number; 'HOST START TS'?: number; 'DEVICE FW DURATION [ns]'?: number; diff --git a/src/functions/math.ts b/src/functions/math.ts index 22527f09..001197b7 100644 --- a/src/functions/math.ts +++ b/src/functions/math.ts @@ -7,8 +7,8 @@ export const toHex = (num: number): string => { return `0x${(num >>> 0).toString(16).toUpperCase()}`; }; -export const formatSize = (number: number): string => { - return new Intl.NumberFormat('en-US').format(number); +export const formatSize = (number: number, decimals?: number): string => { + return new Intl.NumberFormat('en-US', { maximumFractionDigits: decimals }).format(number); }; /** diff --git a/src/hooks/useAPI.tsx b/src/hooks/useAPI.tsx index 78b891e9..9b86d719 100644 --- a/src/hooks/useAPI.tsx +++ b/src/hooks/useAPI.tsx @@ -26,6 +26,8 @@ import { import { BufferType } from '../model/BufferType'; import parseMemoryConfig, { MemoryConfig, memoryConfigPattern } from '../functions/parseMemoryConfig'; import isValidNumber from '../functions/isValidNumber'; +import { getUniqueDeviceIDs, mergeMultideviceRows } from '../functions/perfFunctions'; +import { RowData } from '../definitions/PerfTable'; const parseFileOperationIdentifier = (stackTrace: string): string => { const regex = /File\s+"(?:.+\/)?([^/]+)",\s+line\s+(\d+)/; @@ -350,7 +352,7 @@ export const useGetDeviceOperationsListByOp = () => { }, [operations]); }; -export const useGetDeviceOperationsList = () => { +export const useGetDeviceOperationsList = (): DeviceOperationMapping[] => { const { data: operations } = useOperationsList(); return useMemo(() => { @@ -376,6 +378,52 @@ export const useGetDeviceOperationsList = () => { }, [operations]); }; +export interface DeviceOperationMapping { + name: string; + id: number; + operationName: string; + perfData?: RowData; +} + +export const useGetDeviceOperationListPerf = () => { + const deviceOperations: DeviceOperationMapping[] = useGetDeviceOperationsList(); + const { data } = usePerformance(); + + return useMemo(() => { + if (!data?.data || data.data.length === 0) { + return []; + } + + // @ts-expect-error this should be just fine + let df: RowData[] = data.data.slice() as RowData[]; + + df.forEach((r, index) => { + r.ORIGINAL_ID = index + 2; + }); + + if (df.length > 0 && 'HOST START TS' in df[0]) { + df = df.sort((a, b) => Number(a['HOST START TS'] || 0) - Number(b['HOST START TS'] || 0)); + } + + const uniqueDeviceIDs = getUniqueDeviceIDs(df); + + if (uniqueDeviceIDs.length > 1) { + df = mergeMultideviceRows(df); + } + + df = df.filter((r) => !r['OP CODE']?.toString().includes('(torch)') && !(r['OP CODE']?.toString() === '')); + + deviceOperations.forEach((deviceOperation, index) => { + const perfData = df[index]; + if (perfData && perfData['OP CODE'] === deviceOperation.name) { + deviceOperation.perfData = df[index]; + } + }); + + return deviceOperations; + }, [data, deviceOperations]); +}; + // Not currently used anymore export const useReportMeta = () => { return useQuery('get-report-config', fetchReportMeta); From 7041a62b09b0a68552bfce4c6ba0fa6720a4efab Mon Sep 17 00:00:00 2001 From: David Blundell Date: Thu, 16 Jan 2025 14:43:43 -0500 Subject: [PATCH 03/22] Buffer type moved to Tag component --- src/components/ListItem.tsx | 13 ++++++++++++- src/components/TensorList.tsx | 16 +++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/components/ListItem.tsx b/src/components/ListItem.tsx index e548a513..bf2da919 100644 --- a/src/components/ListItem.tsx +++ b/src/components/ListItem.tsx @@ -4,7 +4,7 @@ import React from 'react'; import classNames from 'classnames'; -import { Icon, IconName, Intent } from '@blueprintjs/core'; +import { Icon, IconName, Intent, Tag, TagProps } from '@blueprintjs/core'; import HighlightedText from './HighlightedText'; import '../scss/components/ListItem.scss'; @@ -14,6 +14,7 @@ interface ListItemProps { icon: IconName; iconColour?: keyof typeof ICON_COLOURS; intent?: Intent; + tags?: TagProps[]; children?: React.ReactNode; } @@ -29,6 +30,7 @@ const ListItem: React.FC = ({ icon, iconColour = 'none', intent = Intent.NONE, + tags, children, }) => { return ( @@ -51,6 +53,15 @@ const ListItem: React.FC = ({ {/* */} {children} + + {tags?.map((tag) => ( + + {tag.htmlTitle} + + ))}
); }; diff --git a/src/components/TensorList.tsx b/src/components/TensorList.tsx index 2937960a..4708a48c 100644 --- a/src/components/TensorList.tsx +++ b/src/components/TensorList.tsx @@ -282,6 +282,16 @@ const TensorList = () => { filterQuery={filterQuery} icon={IconNames.FLOW_LINEAR} iconColour='tensor' + tags={[ + { + htmlTitle: isValidNumber(tensor.buffer_type) + ? BufferTypeLabel[tensor.buffer_type] + : 'n/a', + intent: isValidNumber(tensor.buffer_type) + ? Intent.PRIMARY + : Intent.NONE, + }, + ]} > {tensor.consumers.length > MAX_NUM_CONSUMERS ? ( { ); }; -function getTensorFilterName(tensor: Tensor) { - const bufferTypeLabel = isValidNumber(tensor.buffer_type) ? BufferTypeLabel[tensor.buffer_type] : 'n/a'; - - return `Tensor ${tensor.id} ${bufferTypeLabel}`; -} +const getTensorFilterName = (tensor: Tensor) => `${tensor.id} ${tensor.shape} ${tensor.dtype}`; function getBufferTypeFilterOptions(tensors: Tensor[]) { return [ From 26bd5aa3af34085c9af3953a6eeec8abf0207b70 Mon Sep 17 00:00:00 2001 From: David Blundell Date: Thu, 16 Jan 2025 15:27:03 -0500 Subject: [PATCH 04/22] Operation identifier now computed with function and tags only display for know buffer types --- src/components/BufferDetails.tsx | 5 ++--- src/components/TensorList.tsx | 21 +++++++++++---------- src/functions/getOperationIdentifier.ts | 6 ++++++ src/hooks/useAPI.tsx | 19 ++++++++++++++++++- 4 files changed, 37 insertions(+), 14 deletions(-) create mode 100644 src/functions/getOperationIdentifier.ts diff --git a/src/components/BufferDetails.tsx b/src/components/BufferDetails.tsx index e85bca78..1aca1739 100644 --- a/src/components/BufferDetails.tsx +++ b/src/components/BufferDetails.tsx @@ -14,6 +14,7 @@ import isValidNumber from '../functions/isValidNumber'; import { ShardSpec } from '../functions/parseMemoryConfig'; import MemoryConfigRow from './MemoryConfigRow'; import GoldenTensorComparisonIndicator from './GoldenTensorComparisonIndicator'; +import getOperationIdentifier from '../functions/getOperationIdentifier'; interface BufferDetailsProps { tensor: Tensor; @@ -141,9 +142,7 @@ function getLastOperation(lastOperationId: number, operations: Operation[], tens } return lastOperation ? ( - - {lastOperation?.id} {lastOperation.name} - + {getOperationIdentifier(lastOperation)} ) : null; } diff --git a/src/components/TensorList.tsx b/src/components/TensorList.tsx index 4708a48c..dbf97747 100644 --- a/src/components/TensorList.tsx +++ b/src/components/TensorList.tsx @@ -282,16 +282,17 @@ const TensorList = () => { filterQuery={filterQuery} icon={IconNames.FLOW_LINEAR} iconColour='tensor' - tags={[ - { - htmlTitle: isValidNumber(tensor.buffer_type) - ? BufferTypeLabel[tensor.buffer_type] - : 'n/a', - intent: isValidNumber(tensor.buffer_type) - ? Intent.PRIMARY - : Intent.NONE, - }, - ]} + tags={ + isValidNumber(tensor.buffer_type) && + BufferTypeLabel[tensor.buffer_type] + ? [ + { + htmlTitle: BufferTypeLabel[tensor.buffer_type], + intent: Intent.PRIMARY, + }, + ] + : undefined + } > {tensor.consumers.length > MAX_NUM_CONSUMERS ? ( + `${operation.id} ${operation.name} ${operation.operationFileIdentifier}`; + +export default getOperationIdentifier; diff --git a/src/hooks/useAPI.tsx b/src/hooks/useAPI.tsx index 78b891e9..5690bb40 100644 --- a/src/hooks/useAPI.tsx +++ b/src/hooks/useAPI.tsx @@ -26,6 +26,7 @@ import { import { BufferType } from '../model/BufferType'; import parseMemoryConfig, { MemoryConfig, memoryConfigPattern } from '../functions/parseMemoryConfig'; import isValidNumber from '../functions/isValidNumber'; +import getOperationIdentifier from '../functions/getOperationIdentifier'; const parseFileOperationIdentifier = (stackTrace: string): string => { const regex = /File\s+"(?:.+\/)?([^/]+)",\s+line\s+(\d+)/; @@ -96,11 +97,13 @@ const fetchOperations = async (deviceId?: number): Promise { + operation.operationFileIdentifier = parseFileOperationIdentifier(operation.stack_trace); + const outputs = operation.outputs.map((tensor) => { const tensorWithMetadata = { ...tensor, producerOperation: operation, - operationIdentifier: `${operation.id} ${operation.name} (${parseFileOperationIdentifier(operation.stack_trace)})`, + operationIdentifier: getOperationIdentifier(operation), }; tensorList.set(tensor.id, tensorWithMetadata); return { ...tensorWithMetadata, io: 'output' }; @@ -400,6 +403,20 @@ export const fetchTensors = async (deviceId?: number | null): Promise }, }); + const operationsList = await fetchOperations(); + + for (const tensor of tensorList) { + if (tensor.producers.length > 0) { + const producerId = tensor.producers[0]; + const operationDetails = operationsList.find((operation) => operation.id === producerId); + const outputTensor = operationDetails?.outputs.find((output) => output.id === tensor.id); + + if (outputTensor) { + tensor.operationIdentifier = outputTensor.operationIdentifier; + } + } + } + return tensorList; } catch (error: unknown) { if (axios.isAxiosError(error)) { From b0e4ed4194b1878a71fa64155d182257905b9ac9 Mon Sep 17 00:00:00 2001 From: David Blundell Date: Thu, 16 Jan 2025 15:44:15 -0500 Subject: [PATCH 05/22] Refactored approach --- src/components/BufferDetails.tsx | 7 ++++--- src/functions/getOperationIdentifier.ts | 6 ------ src/hooks/useAPI.tsx | 5 +++-- 3 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 src/functions/getOperationIdentifier.ts diff --git a/src/components/BufferDetails.tsx b/src/components/BufferDetails.tsx index 1aca1739..1e9297b9 100644 --- a/src/components/BufferDetails.tsx +++ b/src/components/BufferDetails.tsx @@ -14,7 +14,6 @@ import isValidNumber from '../functions/isValidNumber'; import { ShardSpec } from '../functions/parseMemoryConfig'; import MemoryConfigRow from './MemoryConfigRow'; import GoldenTensorComparisonIndicator from './GoldenTensorComparisonIndicator'; -import getOperationIdentifier from '../functions/getOperationIdentifier'; interface BufferDetailsProps { tensor: Tensor; @@ -141,8 +140,10 @@ function getLastOperation(lastOperationId: number, operations: Operation[], tens lastOperation = operations.find((operation) => operation.id === tensor.consumers[tensor.consumers.length - 2]); } - return lastOperation ? ( - {getOperationIdentifier(lastOperation)} + const matchingTensor = lastOperation?.inputs.find((input) => input.id === tensor.id); + + return matchingTensor && lastOperation ? ( + {matchingTensor.operationIdentifier} ) : null; } diff --git a/src/functions/getOperationIdentifier.ts b/src/functions/getOperationIdentifier.ts deleted file mode 100644 index 3c5758c2..00000000 --- a/src/functions/getOperationIdentifier.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Operation } from '../model/APIData'; - -const getOperationIdentifier = (operation: Operation) => - `${operation.id} ${operation.name} ${operation.operationFileIdentifier}`; - -export default getOperationIdentifier; diff --git a/src/hooks/useAPI.tsx b/src/hooks/useAPI.tsx index 5690bb40..658a7c22 100644 --- a/src/hooks/useAPI.tsx +++ b/src/hooks/useAPI.tsx @@ -26,7 +26,6 @@ import { import { BufferType } from '../model/BufferType'; import parseMemoryConfig, { MemoryConfig, memoryConfigPattern } from '../functions/parseMemoryConfig'; import isValidNumber from '../functions/isValidNumber'; -import getOperationIdentifier from '../functions/getOperationIdentifier'; const parseFileOperationIdentifier = (stackTrace: string): string => { const regex = /File\s+"(?:.+\/)?([^/]+)",\s+line\s+(\d+)/; @@ -103,9 +102,11 @@ const fetchOperations = async (deviceId?: number): Promise Date: Fri, 17 Jan 2025 09:19:19 -0500 Subject: [PATCH 06/22] Added tensor id and using readable utility functions --- src/components/BufferDetails.tsx | 13 +++++++++---- src/components/TensorList.tsx | 4 +++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/BufferDetails.tsx b/src/components/BufferDetails.tsx index 1e9297b9..17f8ca04 100644 --- a/src/components/BufferDetails.tsx +++ b/src/components/BufferDetails.tsx @@ -31,6 +31,11 @@ function BufferDetails({ tensor, operations, className }: BufferDetailsProps) { <> + + + + + - + @@ -98,7 +98,7 @@ function BufferDetails({ tensor, operations, className }: BufferDetailsProps) { - + {tensor.comparison ? ( From df4d486ff827be9d9850a6b635a3c8b19cac54f4 Mon Sep 17 00:00:00 2001 From: David Blundell Date: Fri, 17 Jan 2025 11:23:54 -0500 Subject: [PATCH 08/22] Checking session for active reports or profiles --- src/components/Layout.tsx | 70 ++++++++++++++++++++------------ src/components/OperationList.tsx | 3 +- src/store/app.ts | 4 +- 3 files changed, 49 insertions(+), 28 deletions(-) diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 8eae30f8..9dd6d0a5 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -5,14 +5,16 @@ import { Link, Outlet } from 'react-router-dom'; import { Classes, Tooltip } from '@blueprintjs/core'; import { Helmet } from 'react-helmet-async'; -import { useAtomValue } from 'jotai'; +import { useAtom } from 'jotai'; import { ToastContainer, cssTransition } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.min.css'; import classNames from 'classnames'; +import { useEffect } from 'react'; import TenstorrentLogo from './TenstorrentLogo'; import ROUTES from '../definitions/routes'; import { activePerformanceTraceAtom, activeReportAtom } from '../store/app'; import MainNavigation from './MainNavigation'; +import { useSession } from '../hooks/useAPI'; const BounceIn = cssTransition({ enter: `Toastify--animate Toastify__bounce-enter`, @@ -26,8 +28,16 @@ const MAX_TITLE_LENGTH = 20; function Layout() { const appVersion = import.meta.env.APP_VERSION; - const activeReport = useAtomValue(activeReportAtom); - const activePerformanceTrace = useAtomValue(activePerformanceTraceAtom); + const [activeReport, setActiveReport] = useAtom(activeReportAtom); + const [activePerformanceTrace, setActivePerformanceTrace] = useAtom(activePerformanceTraceAtom); + const { data: session } = useSession(activeReport, activePerformanceTrace); + + useEffect(() => { + if (session?.active_report) { + setActiveReport(session.active_report?.report_name ?? null); + setActivePerformanceTrace(session.active_report?.profile_name ?? null); + } + }, [session, setActiveReport, setActivePerformanceTrace]); return (
@@ -51,31 +61,41 @@ function Layout() {
- {activeReport && ( - MAX_TITLE_LENGTH, - })} - > - + {activeReport && + (activeReport.length > MAX_TITLE_LENGTH ? ( + MAX_TITLE_LENGTH, + })} + > + + Report: {activeReport} + + + ) : ( + <> Report: {activeReport} - - - )} + + ))} - {activePerformanceTrace && ( - MAX_TITLE_LENGTH, - })} - > - + {activePerformanceTrace && + (activePerformanceTrace.length > MAX_TITLE_LENGTH ? ( + MAX_TITLE_LENGTH, + })} + > + + Performance: {activePerformanceTrace} + + + ) : ( + <> Performance: {activePerformanceTrace} - - - )} + + ))}
diff --git a/src/components/OperationList.tsx b/src/components/OperationList.tsx index 4d0d850b..d1bd6c89 100644 --- a/src/components/OperationList.tsx +++ b/src/components/OperationList.tsx @@ -19,6 +19,7 @@ import ROUTES from '../definitions/routes'; import { expandedOperationsAtom, shouldCollapseAllOperationsAtom } from '../store/app'; import { OperationDescription } from '../model/APIData'; import ListItem from './ListItem'; +import { formatSize } from '../functions/math'; const PLACEHOLDER_ARRAY_SIZE = 10; const OPERATION_EL_HEIGHT = 39; // Height in px of each list item @@ -307,7 +308,7 @@ const OperationList = () => { >

- Python execution time: {operation.duration}s + Python execution time: {formatSize(operation.duration)} s

{operation.arguments && ( diff --git a/src/store/app.ts b/src/store/app.ts index 18b76600..bdb07c7a 100644 --- a/src/store/app.ts +++ b/src/store/app.ts @@ -7,8 +7,8 @@ import { atom } from 'jotai'; import { FileProgress, FileStatus } from '../model/APIData'; export const reportLocationAtom = atom<'local' | 'remote' | null>(null); -export const activeReportAtom = atomWithStorage('activeReport', null); -export const activePerformanceTraceAtom = atomWithStorage('activePerformanceTrace', null); +export const activeReportAtom = atom(null); +export const activePerformanceTraceAtom = atom(null); export const showHexAtom = atomWithStorage('showHex', false); export const isFullStackTraceAtom = atom(false); From 05a46b2acc8e57d348df52dc14c446f260c9132c Mon Sep 17 00:00:00 2001 From: Denis Kartashevskiy Date: Mon, 20 Jan 2025 09:18:20 -0500 Subject: [PATCH 09/22] tweaks, move getUniqueDeviceIDs --- src/components/performance/PerfTable.tsx | 11 +---------- src/functions/perfFunctions.tsx | 9 +++++++++ src/hooks/useAPI.tsx | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/performance/PerfTable.tsx b/src/components/performance/PerfTable.tsx index 782b4dd6..87c4930b 100644 --- a/src/components/performance/PerfTable.tsx +++ b/src/components/performance/PerfTable.tsx @@ -12,6 +12,7 @@ import { color_row, evaluate_fidelity, formatCell, + getUniqueDeviceIDs, get_datatype_size, mergeMultideviceRows, tflops_per_core, @@ -252,16 +253,6 @@ const add_derived_columns = (rows: ProcessedRow[]) => { }); }; -const getUniqueDeviceIDs = (rows: RowData[]): number[] => { - const ids = new Set(); - for (const row of rows) { - if (row['DEVICE ID'] !== undefined) { - ids.add(Number(row['DEVICE ID'])); - } - } - return [...ids]; -}; - // The main React component interface PerformanceReportProps { data?: RowData[]; diff --git a/src/functions/perfFunctions.tsx b/src/functions/perfFunctions.tsx index af25fe24..4d91d7d5 100644 --- a/src/functions/perfFunctions.tsx +++ b/src/functions/perfFunctions.tsx @@ -258,3 +258,12 @@ export const mergeMultideviceRows = (rows: RowData[]): RowData[] => { ); }); }; +export const getUniqueDeviceIDs = (rows: RowData[]): number[] => { + const ids = new Set(); + for (const row of rows) { + if (row['DEVICE ID'] !== undefined) { + ids.add(Number(row['DEVICE ID'])); + } + } + return [...ids]; +}; diff --git a/src/hooks/useAPI.tsx b/src/hooks/useAPI.tsx index 9b86d719..bd2018a5 100644 --- a/src/hooks/useAPI.tsx +++ b/src/hooks/useAPI.tsx @@ -411,7 +411,7 @@ export const useGetDeviceOperationListPerf = () => { df = mergeMultideviceRows(df); } - df = df.filter((r) => !r['OP CODE']?.toString().includes('(torch)') && !(r['OP CODE']?.toString() === '')); + df = df.filter((r) => !r['OP CODE']?.includes('(torch)') && !(r['OP CODE']?.toString() === '')); deviceOperations.forEach((deviceOperation, index) => { const perfData = df[index]; From 634c60536dcf2bfa35f46c884f4137123e08e1db Mon Sep 17 00:00:00 2001 From: David Blundell Date: Mon, 20 Jan 2025 10:12:31 -0500 Subject: [PATCH 10/22] Add new title --- src/components/Layout.tsx | 5 ++++- src/scss/_layout.scss | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index a3f8c92c..a6a3e058 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -38,7 +38,10 @@ function Layout() {
diff --git a/src/scss/_layout.scss b/src/scss/_layout.scss index 45d49976..13a1fc04 100644 --- a/src/scss/_layout.scss +++ b/src/scss/_layout.scss @@ -11,6 +11,19 @@ display: flex; align-items: center; justify-content: space-between; + + .title { + display: flex; + justify-content: flex-start; + align-items: center; + gap: 10px; + flex-wrap: wrap; + + h1, + p { + margin: 0; + } + } } .current-data { From 53f9cc74522ceb48ecfec19c83851fddc924ac97 Mon Sep 17 00:00:00 2001 From: David Blundell Date: Mon, 20 Jan 2025 10:14:45 -0500 Subject: [PATCH 11/22] Update styles --- src/scss/_layout.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/scss/_layout.scss b/src/scss/_layout.scss index 13a1fc04..2da2f626 100644 --- a/src/scss/_layout.scss +++ b/src/scss/_layout.scss @@ -19,8 +19,7 @@ gap: 10px; flex-wrap: wrap; - h1, - p { + h1 { margin: 0; } } From 6d9f2dfd2463de7fc2f3ebe1391afb2259d7f5bb Mon Sep 17 00:00:00 2001 From: David Blundell Date: Mon, 20 Jan 2025 11:35:23 -0500 Subject: [PATCH 12/22] Updated docs --- docs/contributing.md | 46 +++++--------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index 736d06aa..5c3c67fb 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,46 +1,14 @@ # Contributing -## React + TypeScript + Vite {#react-typescript-vite} +**NOTE:** If you're just looking to run the app, [using the wheel](https://github.com/tenstorrent/ttnn-visualizer/blob/dev/docs/getting-started.md) is recommended as it is very simple to install and run. -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +## Running the app from source -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) - uses [Babel](https://babeljs.io/) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast - Refresh - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: - -- Configure the top-level `parserOptions` property like this: - -```js -export default { - // other rules... - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module', - project: ['./tsconfig.json', './tsconfig.node.json'], - tsconfigRootDir: __dirname, - }, -} -``` - -- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` - or `plugin:@typescript-eslint/strict-type-checked` -- Optionally add `plugin:@typescript-eslint/stylistic-type-checked` -- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and - add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list +### Environment -## Running the app +Copy the provided `.env.sample` file to `.env`. The values from the sample should work as is but `VITE_API_ROOT` is required to be able to communicate with the backend. -### Environment -Copy the provided `.env.sample` file to `.env` and change any necessary options. See the section on options -for more details on the available configuration options. ### Frontend @@ -82,11 +50,7 @@ Starting with hot reload: npm run flask:start-debug ``` -access on localhost:8000/ - -### Development - -Copy report contents to `backend/data/active` - IE - `backend/data/active/db.sqlite` +When both the frontend and backend are running you can access the app on [http://localhost:5173](http://localhost:5173) or whatever **Local** uri is printed in your terminal where you ran `npm run dev`. ## Troubleshooting From c3975b534692e0b63c128391e8145317aaf51a32 Mon Sep 17 00:00:00 2001 From: Scott Mountenay Date: Mon, 20 Jan 2025 16:05:41 -0600 Subject: [PATCH 13/22] Add PyYAML to pyproject.toml dependencies (#326) --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 998db1b5..82075574 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,7 +19,8 @@ dependencies = [ "python-dotenv==1.0.1", "sqlalchemy==2.0.34", "flask-socketio==5.4.1", - "flask-sqlalchemy==3.1.1" + "flask-sqlalchemy==3.1.1", + "PyYAML==6.0.2" ] classifiers = [ From 1b762a06cb0f3fe2bd6fa49d776ccae6e19880ef Mon Sep 17 00:00:00 2001 From: Denis Kartashevskiy Date: Tue, 21 Jan 2025 09:09:06 -0500 Subject: [PATCH 14/22] improved tensor information rendering --- src/components/OperationGraphComponent.tsx | 4 ++-- src/components/operation-details/MemoryLegendElement.tsx | 4 ++-- .../operation-details/OperationDetailsComponent.tsx | 6 +++--- .../operation-details/TensorDetailsComponent.tsx | 8 ++++---- src/functions/getChartData.ts | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/components/OperationGraphComponent.tsx b/src/components/OperationGraphComponent.tsx index 23b8a9ab..95875499 100644 --- a/src/components/OperationGraphComponent.tsx +++ b/src/components/OperationGraphComponent.tsx @@ -167,7 +167,7 @@ const OperationGraph: React.FC<{ } }); - // keeping this for now in case we resurect this soon + // keeping this for now in case we resurrect this soon // networkRef.current.on('dragEnd', () => { // if (networkRef.current) { // const centerPosition = networkRef.current.getViewPosition(); @@ -322,7 +322,7 @@ const OperationGraph: React.FC<{
diff --git a/src/components/operation-details/OperationDetailsComponent.tsx b/src/components/operation-details/OperationDetailsComponent.tsx index 35ae415f..a581ddff 100644 --- a/src/components/operation-details/OperationDetailsComponent.tsx +++ b/src/components/operation-details/OperationDetailsComponent.tsx @@ -229,7 +229,7 @@ const OperationDetailsComponent: React.FC = ({ operationI /> ) : null} - {isL1Active && ( + {isL1Active && operation && ( <>

L1 Memory{' '} @@ -264,7 +264,7 @@ const OperationDetailsComponent: React.FC = ({ operationI {tensixIOVisualisationOpen && ( = ({ operationI )} {tensixFullVisualisationOpen && ( = ({ )} {overlayOpen && address !== null && tensor.buffer_type !== null && ( = ({

)}

- Shape: {tensor.shape} + Shape: {toReadableShape(tensor.shape)}

- Dtype: {tensor.dtype} + Dtype: {toReadableType(tensor.dtype)}

Layout: {tensor.layout} diff --git a/src/functions/getChartData.ts b/src/functions/getChartData.ts index cc67bd94..a6911e18 100644 --- a/src/functions/getChartData.ts +++ b/src/functions/getChartData.ts @@ -3,7 +3,7 @@ // SPDX-FileCopyrightText: © 2024 Tenstorrent AI ULC import { getBufferColor, getTensorColor } from './colorGenerator'; -import { formatSize, toHex } from './math'; +import { formatSize, toHex, toReadableShape, toReadableType } from './math'; import { BufferPage, Chunk, ColoredChunk, Tensor } from '../model/APIData'; import { PlotDataCustom } from '../definitions/PlotConfigurations'; import { TensorMemoryLayout } from './parseMemoryConfig'; @@ -89,7 +89,7 @@ export default function getChartData( : ` ${address} (${toHex(address)})
Size: ${formatSize(size)} -${tensor ? `
Tensor ${tensor.id}
${tensorMemoryLayout || ''}` : ''} +${tensor ? `
${toReadableShape(tensor.shape)} ${toReadableType(tensor.dtype)} Tensor${tensor.id}
${tensorMemoryLayout || ''}` : ''} `, hoverlabel: { From a42b5a537084725438bcfa1f0e64d1d2ccd5e284 Mon Sep 17 00:00:00 2001 From: Denis Kartashevskiy Date: Tue, 21 Jan 2025 09:37:51 -0500 Subject: [PATCH 15/22] consistency id use --- .../operation-details/OperationDetailsComponent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/operation-details/OperationDetailsComponent.tsx b/src/components/operation-details/OperationDetailsComponent.tsx index a581ddff..aaf99327 100644 --- a/src/components/operation-details/OperationDetailsComponent.tsx +++ b/src/components/operation-details/OperationDetailsComponent.tsx @@ -264,7 +264,7 @@ const OperationDetailsComponent: React.FC = ({ operationI {tensixIOVisualisationOpen && ( = ({ operationI )} {tensixFullVisualisationOpen && ( Date: Tue, 21 Jan 2025 11:19:27 -0500 Subject: [PATCH 16/22] Code cleanup, and moved styling of tags to classes rather than intent --- src/components/BufferDetails.tsx | 10 +++++----- src/components/ListItem.tsx | 7 +------ src/components/TensorList.tsx | 5 ++++- src/scss/components/ListView.scss | 8 ++++++++ 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/components/BufferDetails.tsx b/src/components/BufferDetails.tsx index c7be3e0b..75046be1 100644 --- a/src/components/BufferDetails.tsx +++ b/src/components/BufferDetails.tsx @@ -76,6 +76,11 @@ function BufferDetails({ tensor, operations, className }: BufferDetailsProps) {

+ + + + + @@ -96,11 +101,6 @@ function BufferDetails({ tensor, operations, className }: BufferDetailsProps) { )) : null} - - - - - {tensor.comparison ? ( <> diff --git a/src/components/ListItem.tsx b/src/components/ListItem.tsx index bf2da919..a897d146 100644 --- a/src/components/ListItem.tsx +++ b/src/components/ListItem.tsx @@ -47,17 +47,12 @@ const ListItem: React.FC = ({ filter={filterQuery} /> - {/*
Tensor Id{tensor.id}
Last used @@ -140,10 +145,10 @@ function getLastOperation(lastOperationId: number, operations: Operation[], tens lastOperation = operations.find((operation) => operation.id === tensor.consumers[tensor.consumers.length - 2]); } - const matchingTensor = lastOperation?.inputs.find((input) => input.id === tensor.id); - - return matchingTensor && lastOperation ? ( - {matchingTensor.operationIdentifier} + return lastOperation ? ( + + {lastOperation?.id} {lastOperation.name} ({lastOperation.operationFileIdentifier}) + ) : null; } diff --git a/src/components/TensorList.tsx b/src/components/TensorList.tsx index dbf97747..850b0dc7 100644 --- a/src/components/TensorList.tsx +++ b/src/components/TensorList.tsx @@ -25,6 +25,7 @@ import 'styles/components/TensorList.scss'; import BufferDetails from './BufferDetails'; import isValidNumber from '../functions/isValidNumber'; import { MAX_NUM_CONSUMERS } from '../definitions/ProducersConsumers'; +import { toReadableShape, toReadableType } from '../functions/math'; const PLACEHOLDER_ARRAY_SIZE = 10; const OPERATION_EL_HEIGHT = 39; // Height in px of each list item @@ -332,7 +333,8 @@ const TensorList = () => { ); }; -const getTensorFilterName = (tensor: Tensor) => `${tensor.id} ${tensor.shape} ${tensor.dtype}`; +const getTensorFilterName = (tensor: Tensor) => + `${toReadableShape(tensor.shape)} ${toReadableType(tensor.dtype)} ${tensor.operationIdentifier ? tensor.operationIdentifier : ''}`; function getBufferTypeFilterOptions(tensors: Tensor[]) { return [ From 0a03c83197f1274a5a3d601027ff0ab27ff777a0 Mon Sep 17 00:00:00 2001 From: David Blundell Date: Fri, 17 Jan 2025 09:58:41 -0500 Subject: [PATCH 07/22] Using readable functions further --- src/components/BufferDetails.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/BufferDetails.tsx b/src/components/BufferDetails.tsx index 17f8ca04..c7be3e0b 100644 --- a/src/components/BufferDetails.tsx +++ b/src/components/BufferDetails.tsx @@ -5,7 +5,7 @@ import classNames from 'classnames'; import { Link } from 'react-router-dom'; import { Operation, OperationDescription, Tensor } from '../model/APIData'; -import { toHex } from '../functions/math'; +import { toHex, toReadableShape, toReadableType } from '../functions/math'; import ROUTES from '../definitions/routes'; import 'styles/components/BufferDetails.scss'; import getDeallocationOperation from '../functions/getDeallocationOperation'; @@ -78,7 +78,7 @@ function BufferDetails({ tensor, operations, className }: BufferDetailsProps) {
DataType{dtype}{toReadableType(dtype)}
Shape{shape}{toReadableShape(shape)}
{tensor.device_id ?? 'n/a'}
Shape{toReadableShape(shape)}
DataType {toReadableType(dtype)}
Shape{toReadableShape(shape)}