@@ -204,6 +204,7 @@ export class ModelTestContext {
204
204
readonly perfData : ModelTestContext . ModelTestPerfData ,
205
205
readonly ioBinding : Test . IOBindingMode ,
206
206
private readonly profile : boolean ,
207
+ public readonly mlContext ?: MLContext ,
207
208
) { }
208
209
209
210
/**
@@ -254,7 +255,25 @@ export class ModelTestContext {
254
255
255
256
const initStart = now ( ) ;
256
257
const executionProviderConfig =
257
- modelTest . backend === 'webnn' ? ( testOptions ?. webnnOptions || 'webnn' ) : modelTest . backend ! ;
258
+ modelTest . backend === 'webnn' ? ( testOptions ?. webnnOptions || { name : 'webnn' } ) : modelTest . backend ! ;
259
+ let mlContext : MLContext | undefined ;
260
+ if ( modelTest . ioBinding . includes ( 'ml-tensor' ) || modelTest . ioBinding . includes ( 'ml-location' ) ) {
261
+
262
+ const webnnOptions = executionProviderConfig as ort . InferenceSession . WebNNExecutionProviderOption ;
263
+ const deviceType = ( webnnOptions as ort . InferenceSession . WebNNContextOptions ) ?. deviceType ;
264
+ const numThreads = ( webnnOptions as ort . InferenceSession . WebNNContextOptions ) ?. numThreads ;
265
+ const powerPreference = ( webnnOptions as ort . InferenceSession . WebNNContextOptions ) ?. powerPreference ;
266
+
267
+ mlContext = await navigator . ml . createContext ( {
268
+ deviceType,
269
+ numThreads,
270
+ powerPreference,
271
+ } ) ;
272
+ ( executionProviderConfig as ort . InferenceSession . WebNNExecutionProviderOption ) . context = mlContext ;
273
+ if ( ! deviceType ) {
274
+ ( executionProviderConfig as ort . InferenceSession . WebNNContextOptions ) . deviceType = deviceType ;
275
+ }
276
+ }
258
277
const session = await initializeSession (
259
278
modelTest . modelUrl , executionProviderConfig , modelTest . ioBinding , profile , modelTest . externalData ,
260
279
testOptions ?. sessionOptions || { } , this . cache ) ;
@@ -271,6 +290,7 @@ export class ModelTestContext {
271
290
{ init : initEnd - initStart , firstRun : - 1 , runs : [ ] , count : 0 } ,
272
291
modelTest . ioBinding ,
273
292
profile ,
293
+ mlContext ,
274
294
) ;
275
295
} finally {
276
296
this . initializing = false ;
@@ -565,46 +585,34 @@ function createGpuTensorForOutput(type: ort.Tensor.Type, dims: readonly number[]
565
585
} ) ;
566
586
}
567
587
568
- const getContext = ( ( ) => {
569
- let context : MLContext | undefined ;
570
-
571
- return async ( ) : Promise < MLContext > => {
572
- if ( ! context ) {
573
- context = await navigator . ml . createContext ( ) ;
574
- }
575
- return context ;
576
- } ;
577
- } ) ( ) ;
578
588
579
- async function createMlTensorForOutput ( type : ort . Tensor . Type , dims : readonly number [ ] ) {
589
+ async function createMLTensorForOutput ( mlContext : MLContext , type : ort . Tensor . Type , dims : readonly number [ ] ) {
580
590
if ( ! isMLBufferSupportedType ( type ) ) {
581
- throw new Error ( `createMlTensorForOutput can not work with ${ type } tensor` ) ;
591
+ throw new Error ( `createMLTensorForOutput can not work with ${ type } tensor` ) ;
582
592
}
583
593
584
594
const dataType = type === 'bool' ? 'uint8' : type ;
585
595
586
- const context = await getContext ( ) ;
587
- const mlBuffer = context . createBuffer ( { dataType, dimensions : dims as number [ ] } ) ;
596
+ const mlBuffer = mlContext . createBuffer ( { dataType, dimensions : dims as number [ ] } ) ;
588
597
589
598
return ort . Tensor . fromMLBuffer ( mlBuffer , {
590
599
dataType : type ,
591
600
dims,
592
601
dispose : ( ) => mlBuffer . destroy ( ) ,
593
602
download : async ( ) => {
594
- const arrayBuffer = await context . readBuffer ( mlBuffer ) ;
595
- return createView ( arrayBuffer , type ) as ort . Tensor . DataTypeMap [ ort . Tensor . GpuBufferDataTypes ] ;
603
+ const arrayBuffer = await mlContext . readBuffer ( mlBuffer ) ;
604
+ return createView ( arrayBuffer , type ) as ort . Tensor . DataTypeMap [ ort . Tensor . MLBufferDataTypes ] ;
596
605
}
597
606
} ) ;
598
607
}
599
608
600
- async function createMlTensorForInput ( cpuTensor : ort . Tensor ) : Promise < ort . Tensor > {
609
+ async function createMLTensorForInput ( mlContext : MLContext , cpuTensor : ort . Tensor ) : Promise < ort . Tensor > {
601
610
if ( ! isMLBufferSupportedType ( cpuTensor . type ) || Array . isArray ( cpuTensor . data ) ) {
602
- throw new Error ( `createMlTensorForInput can not work with ${ cpuTensor . type } tensor` ) ;
611
+ throw new Error ( `createMLTensorForInput can not work with ${ cpuTensor . type } tensor` ) ;
603
612
}
604
- const context = await getContext ( ) ;
605
613
const dataType = cpuTensor . type === 'bool' ? 'uint8' : cpuTensor . type ;
606
- const mlBuffer = context . createBuffer ( { dataType, dimensions : cpuTensor . dims as number [ ] } ) ;
607
- context . writeBuffer ( mlBuffer , cpuTensor . data ) ;
614
+ const mlBuffer = mlContext . createBuffer ( { dataType, dimensions : cpuTensor . dims as number [ ] } ) ;
615
+ mlContext . writeBuffer ( mlBuffer , cpuTensor . data ) ;
608
616
return ort . Tensor . fromMLBuffer (
609
617
mlBuffer , { dataType : cpuTensor . type , dims : cpuTensor . dims , dispose : ( ) => mlBuffer . destroy ( ) } ) ;
610
618
}
@@ -613,6 +621,7 @@ export async function sessionRun(options: {
613
621
session : ort . InferenceSession ; feeds : Record < string , ort . Tensor > ;
614
622
outputsMetaInfo : Record < string , Pick < ort . Tensor , 'dims' | 'type' > > ;
615
623
ioBinding : Test . IOBindingMode ;
624
+ mlContext ?: MLContext ;
616
625
} ) : Promise < [ number , number , ort . InferenceSession . OnnxValueMapType ] > {
617
626
const session = options . session ;
618
627
const feeds = options . feeds ;
@@ -633,7 +642,7 @@ export async function sessionRun(options: {
633
642
if ( Object . hasOwnProperty . call ( feeds , name ) ) {
634
643
if ( feeds [ name ] . size > 0 ) {
635
644
if ( options . ioBinding === 'ml-location' || options . ioBinding === 'ml-tensor' ) {
636
- feeds [ name ] = await createMlTensorForInput ( feeds [ name ] ) ;
645
+ feeds [ name ] = await createMLTensorForInput ( options . mlContext ! , feeds [ name ] ) ;
637
646
} else {
638
647
feeds [ name ] = createGpuTensorForInput ( feeds [ name ] ) ;
639
648
}
@@ -650,7 +659,7 @@ export async function sessionRun(options: {
650
659
fetches [ name ] = new ort . Tensor ( type , [ ] , dims ) ;
651
660
} else {
652
661
if ( options . ioBinding === 'ml-tensor' ) {
653
- fetches [ name ] = await createMlTensorForOutput ( type , dims ) ;
662
+ fetches [ name ] = await createMLTensorForOutput ( options . mlContext ! , type , dims ) ;
654
663
} else {
655
664
fetches [ name ] = createGpuTensorForOutput ( type , dims ) ;
656
665
}
@@ -701,8 +710,8 @@ export async function runModelTestSet(
701
710
const outputsMetaInfo : Record < string , ort . Tensor > = { } ;
702
711
testCase . inputs ! . forEach ( ( tensor ) => feeds [ tensor . name ] = tensor ) ;
703
712
testCase . outputs ! . forEach ( ( tensor ) => outputsMetaInfo [ tensor . name ] = tensor ) ;
704
- const [ start , end , outputs ] =
705
- await sessionRun ( { session : context . session , feeds, outputsMetaInfo, ioBinding : context . ioBinding } ) ;
713
+ const [ start , end , outputs ] = await sessionRun (
714
+ { session : context . session , feeds, outputsMetaInfo, ioBinding : context . ioBinding , mlContext : context . mlContext } ) ;
706
715
if ( context . perfData . count === 0 ) {
707
716
context . perfData . firstRun = end - start ;
708
717
} else {
0 commit comments