@@ -692,6 +692,10 @@ <h1>Benchmark Dashboard</h1>
692692 return row . model || 'unknown' ;
693693}
694694
695+ function atomeshBaseModelName ( model ) {
696+ return String ( model || 'unknown' ) . replace ( / - E a g l e 3 $ / i, '' ) ;
697+ }
698+
695699function atomeshMergeScore ( row ) {
696700 return parseAtomeshNumber ( row . totalTput ) ;
697701}
@@ -3532,35 +3536,55 @@ <h3>${escHTML(model)} MTP Acceptance</h3>
35323536 container . innerHTML = '<div class="chart-empty">No completed ATOMesh performance row matches the current filters.</div>' ;
35333537 return ;
35343538 }
3535- const groups = { } ;
3539+ const chartGroups = { } ;
35363540 for ( const c of completed ) {
3537- const key = `${ c . model } |${ c . islOsl } ` ;
3538- if ( ! groups [ key ] ) groups [ key ] = [ ] ;
3539- groups [ key ] . push ( c ) ;
3540- }
3541- const datasets = Object . values ( groups ) . map ( groupRows => {
3542- groupRows . sort ( ( a , b ) => a . concurrency - b . concurrency ) ;
3543- const first = groupRows [ 0 ] ;
3544- const color = getModelColor ( ATOMESH_DATA . backend , first . model ) ;
3541+ const chartKey = atomeshBaseModelName ( c . model ) ;
3542+ if ( ! chartGroups [ chartKey ] ) chartGroups [ chartKey ] = [ ] ;
3543+ chartGroups [ chartKey ] . push ( c ) ;
3544+ }
3545+ const chartSpecs = Object . entries ( chartGroups ) . sort ( ( [ a ] , [ b ] ) => _lc ( a , b ) ) . map ( ( [ model , modelRows ] , chartIdx ) => {
3546+ const seriesGroups = { } ;
3547+ for ( const row of modelRows ) {
3548+ const topology = row . sourceTopology || row . topology || 'unknown' ;
3549+ const key = `${ row . model } |${ topology } |${ row . islOsl } ` ;
3550+ if ( ! seriesGroups [ key ] ) seriesGroups [ key ] = [ ] ;
3551+ seriesGroups [ key ] . push ( row ) ;
3552+ }
3553+ const datasets = Object . values ( seriesGroups ) . map ( groupRows => {
3554+ groupRows . sort ( ( a , b ) => a . concurrency - b . concurrency ) ;
3555+ const first = groupRows [ 0 ] ;
3556+ const color = getModelColor ( ATOMESH_DATA . backend , first . model ) ;
3557+ const topology = first . sourceTopology || first . topology || 'unknown' ;
3558+ return {
3559+ label : `${ first . model } ${ topology } ${ first . islOsl } ` ,
3560+ data : groupRows . map ( c => ( { x : c . interactivity , y : c . totalTputPerGpu , row : c } ) ) ,
3561+ borderColor : color . border ,
3562+ backgroundColor : color . border ,
3563+ borderWidth : 2 ,
3564+ pointRadius : 4 ,
3565+ pointHoverRadius : 6 ,
3566+ pointBorderWidth : 0 ,
3567+ pointHoverBorderWidth : 0 ,
3568+ showLine : groupRows . length > 1 ,
3569+ } ;
3570+ } ) ;
35453571 return {
3546- label : `${ first . model } ${ first . islOsl } ` ,
3547- data : groupRows . map ( c => ( { x : c . interactivity , y : c . totalTputPerGpu , row : c } ) ) ,
3548- borderColor : color . border ,
3549- backgroundColor : color . border ,
3550- borderWidth : 2 ,
3551- pointRadius : 4 ,
3552- pointHoverRadius : 6 ,
3553- pointBorderWidth : 0 ,
3554- pointHoverBorderWidth : 0 ,
3555- showLine : groupRows . length > 1 ,
3572+ id : `atomesh-tradeoff-${ chartIdx } ` ,
3573+ model,
3574+ rows : modelRows ,
3575+ datasets,
35563576 } ;
35573577 } ) ;
35583578
35593579 let html = `<div class="section-container"><div class="section-header">
35603580 <span class="section-title">ATOMesh Token Throughput per GPU vs. Interactivity</span>
35613581 <span style="font-size:11px;color:var(--text-tertiary);overflow-wrap:anywhere">${ completed . length } /${ atomeshRows ( ) . length } selected rows · source: benchmark-action data.js</span>
35623582 </div>
3563- <div class="chart-card hero"><h3>${ ATOMESH_DATA . backend } · ${ datasets . length } selected series</h3><div class="chart-wrap"><canvas id="atomesh-tradeoff"></canvas></div></div></div>` ;
3583+ <div class="chart-grid">${ chartSpecs . map ( spec => `
3584+ <div class="chart-card ${ chartSpecs . length === 1 ? 'hero' : 'half' } ">
3585+ <h3>${ escHTML ( spec . model ) } · ${ spec . datasets . length } selected series</h3>
3586+ <div class="chart-wrap"><canvas id="${ spec . id } "></canvas></div>
3587+ </div>` ) . join ( '' ) } </div></div>`;
35643588
35653589 html += `<div class="section-container"><div class="section-header"><span class="section-title">Detail Table</span></div>
35663590 <div class="table-watermark"><div class="table-watermark-scroll"><table class="perf-table"><thead><tr>
@@ -3600,41 +3624,43 @@ <h3>${escHTML(model)} MTP Acceptance</h3>
36003624 } ) ;
36013625 } ) ;
36023626
3603- new Chart ( document . getElementById ( 'atomesh-tradeoff' ) , {
3604- type : 'scatter' ,
3605- data : { datasets } ,
3606- options : {
3607- responsive : true ,
3608- maintainAspectRatio : false ,
3609- layout : { padding : { top : 8 , right : 16 } } ,
3610- plugins : {
3611- legend : { labels : { color : C_LEGEND , font : { size : 10 } , boxWidth : 10 } } ,
3612- tooltip : { ...chartTooltipOpts ( ) , callbacks : {
3613- title : items => {
3614- const c = items [ 0 ] . raw . row ;
3615- return `${ c . model } ${ c . islOsl } · c=${ c . concurrency } · ${ c . sourceTopology || c . topology } ` ;
3616- } ,
3617- label : item => [
3618- ` Interactivity: ${ fmtNum ( item . parsed . x , 2 ) } tok/s/user` ,
3619- ` Total tok/s/GPU: ${ fmtNum ( item . parsed . y , 2 ) } ` ,
3620- ` GSM8K: ${ item . raw . row . gsm8kRaw || '—' } ` ,
3621- ] ,
3622- afterBody : ( ) => '\nClick for details' ,
3623- } } ,
3624- datalabels : { display : true , color : C_LEGEND , align : 'top' , formatter : value => 'c' + value . row . concurrency } ,
3625- } ,
3626- scales : {
3627- x : { grid : chartGridOpts ( ) , title : { display : true , text : 'Interactivity (tok/s/user)' , color : C_TICK } , ticks : { color : C_TICK } , grace : '10%' } ,
3628- y : { grid : chartGridOpts ( ) , title : { display : true , text : 'Token Throughput per GPU (tok/s/gpu)' , color : C_TICK } , ticks : { color : C_TICK } , grace : '10%' } ,
3629- } ,
3630- onClick : ( _e , elems ) => {
3631- if ( ! elems . length ) return ;
3632- const item = elems [ 0 ] ;
3633- const row = datasets [ item . datasetIndex ] ?. data ?. [ item . index ] ?. row ;
3634- if ( row ) showAtomeshPopover ( row ) ;
3627+ for ( const spec of chartSpecs ) {
3628+ new Chart ( document . getElementById ( spec . id ) , {
3629+ type : 'scatter' ,
3630+ data : { datasets : spec . datasets } ,
3631+ options : {
3632+ responsive : true ,
3633+ maintainAspectRatio : false ,
3634+ layout : { padding : { top : 8 , right : 16 } } ,
3635+ plugins : {
3636+ legend : { labels : { color : C_LEGEND , font : { size : 10 } , boxWidth : 10 } } ,
3637+ tooltip : { ...chartTooltipOpts ( ) , callbacks : {
3638+ title : items => {
3639+ const c = items [ 0 ] . raw . row ;
3640+ return `${ c . model } ${ c . islOsl } · c=${ c . concurrency } · ${ c . sourceTopology || c . topology } ` ;
3641+ } ,
3642+ label : item => [
3643+ ` Interactivity: ${ fmtNum ( item . parsed . x , 2 ) } tok/s/user` ,
3644+ ` Total tok/s/GPU: ${ fmtNum ( item . parsed . y , 2 ) } ` ,
3645+ ` GSM8K: ${ item . raw . row . gsm8kRaw || '—' } ` ,
3646+ ] ,
3647+ afterBody : ( ) => '\nClick for details' ,
3648+ } } ,
3649+ datalabels : { display : true , color : C_LEGEND , align : 'top' , formatter : value => 'c' + value . row . concurrency } ,
3650+ } ,
3651+ scales : {
3652+ x : { grid : chartGridOpts ( ) , title : { display : true , text : 'Interactivity (tok/s/user)' , color : C_TICK } , ticks : { color : C_TICK } , grace : '10%' } ,
3653+ y : { grid : chartGridOpts ( ) , title : { display : true , text : 'Token Throughput per GPU (tok/s/gpu)' , color : C_TICK } , ticks : { color : C_TICK } , grace : '10%' } ,
3654+ } ,
3655+ onClick : ( _e , elems ) => {
3656+ if ( ! elems . length ) return ;
3657+ const item = elems [ 0 ] ;
3658+ const row = spec . datasets [ item . datasetIndex ] ?. data ?. [ item . index ] ?. row ;
3659+ if ( row ) showAtomeshPopover ( row ) ;
3660+ } ,
36353661 } ,
3636- } ,
3637- } ) ;
3662+ } ) ;
3663+ }
36383664 syncHeaderH ( ) ;
36393665 bindFixedThead ( container ) ;
36403666}
0 commit comments