license import { backend_util , BackendTimingInfo , buffer , DataStorage , DataType , DataValues , engine , env , kernel_impls , KernelBackend , Rank , ShapeMap , Tensor , Tensor2D , TensorBuffer , TensorInfo , TypedArray , util } from '@tensorflow/tfjs-core' ; const whereImpl = kernel_impls . whereImpl ; import { assertNotComplex } from './cpu_util' ; interface DataId { } export interface TensorData < D extends DataType > { values ? : backend_util . BackendValues ; dtype : D ; complexTensorInfos ? : { real : TensorInfo ; imag : TensorInfo ; } ; refCount : number ; } export class MathBackendCPU extends KernelBackend { public blockSize = 48 ; data : DataStorage < TensorData < DataType > > ; private firstUse = true ; private static nextDataId = 0 ; private nextDataId ( ) { return MathBackendCPU . nextDataId ++ ; } constructor ( ) { super ( ) ; this . data = new DataStorage ( this , engine ( ) ) ; } write ( values , shape , dtype ) { if ( this . firstUse ) { this . firstUse = false ; if ( env ( ) . get ( 'IS_NODE' ) ) { backend_util . warn ( '\n============================\n' + 'Hi there 👋. Looks like you are running TensorFlow.js in ' + 'Node.js. To speed things up dramatically, install our node ' + 'backend, which binds to TensorFlow C++, by running ' + 'npm i @tensorflow/tfjs-node, ' + 'or npm i @tensorflow/tfjs-node-gpu if you have CUDA. ' + 'Then call require(\'@tensorflow/tfjs-node\'); (-gpu ' + 'suffix for CUDA) at the start of your program. ' + 'Visit https://github.com/tensorflow/tfjs-node for more details.' + '\n============================' ) ; } } const dataId = { id : this . nextDataId ( ) } ; this . data . set ( dataId , { values , dtype , refCount : 1 } ) ; return dataId ; } param shape param dtype param values makeTensorInfo ( shape , dtype , values ? ) { let outId ; if ( dtype === 'string' && values != null && values . length > 0 && util . isString ( values [ 0 ] ) ) { const encodedValues = ( values as { } as string [ ] ) . map ( d => util . encodeString ( d ) ) ; outId = this . write ( encodedValues , shape , dtype ) ; } else { outId = this . write ( values as TypedArray , shape , dtype ) ; } return { dataId : outId , shape , dtype } ; } /** Return refCount of a `TensorData`. */ refCount ( dataId ) { if ( this . data . has ( dataId ) ) { const tensorData = this . data . get ( dataId ) ; return tensorData . refCount ; } return 0 ; } /** Increase refCount of a `TensorData`. */ incRef ( dataId ) { const tensorData = this . data . get ( dataId ) ; tensorData . refCount ++ ; } /** Decrease refCount of a `TensorData`. */ decRef ( dataId ) { if ( this . data . has ( dataId ) ) { const tensorData = this . data . get ( dataId ) ; tensorData . refCount -- ; } } move ( dataId , values , shape , dtype , refCount ) { this . data . set ( dataId , { values , dtype , refCount } ) ; } numDataIds ( ) { return this . data . numDataIds ( ) ; } async read ( dataId ) { return this . readSync ( dataId ) ; } readSync ( dataId ) { const { dtype , complexTensorInfos } = this . data . get ( dataId ) ; if ( dtype === 'complex64' ) { const realValues = this . readSync ( complexTensorInfos . real . dataId ) as Float32Array ; const imagValues = this . readSync ( complexTensorInfos . imag . dataId ) as Float32Array ; return backend_util . mergeRealAndImagArrays ( realValues , imagValues ) ; } return this . data . get ( dataId ) . values ; } bufferSync < R extends Rank > ( t ) { const data = this . readSync ( t . dataId ) ; let decodedData = data as DataValues ; if ( t . dtype === 'string' ) { try { decodedData = ( data as Uint8Array [ ] ) . map ( d => util . decodeString ( d ) ) ; } catch { throw new Error ( 'Failed to decode encoded string bytes into utf-8' ) ; } } return buffer ( t . shape as ShapeMap [ R ] , t . dtype , decodedData ) as TensorBuffer < R > ; } makeOutput < T extends Tensor > ( values , shape , dtype ) { const dataId = this . write ( values , shape , dtype ) ; return engine ( ) . makeTensorFromDataId ( dataId , shape , dtype , this ) as T ; } param dataId oaram disposeData ( dataId , force = false ) { if ( this . data . has ( dataId ) ) { this . data . get ( dataId ) . refCount -- ; if ( ! force && this . data . get ( dataId ) . refCount > 0 ) { return false ; } const { complexTensorInfos } = this . data . get ( dataId ) ; if ( complexTensorInfos != null ) { this . disposeData ( complexTensorInfos . real . dataId , true ) ; this . disposeData ( complexTensorInfos . imag . dataId , true ) ; } this . data . delete ( dataId ) ; } return true ; } disposeIntermediateTensorInfo ( tensorInfo ) { this . disposeData ( tensorInfo . dataId ) ; } async time ( f ) { const start = util . now ( ) ; f ( ) ; const kernelMs = util . now ( ) - start ; return { kernelMs } ; } memory ( ) { return { unreliable : true , reasons : [ 'The reported memory is an upper bound. Due to automatic garbage ' + 'collection, the true allocated memory may be less.' ] } ; } where ( condition ) { assertNotComplex ( [ condition ] , 'where' ) ; const condVals = this . readSync ( condition . dataId ) as TypedArray ; return whereImpl ( condition . shape , condVals ) ; } dispose ( ) { } floatPrecision ( ) { return 32 ; } /** Returns the smallest representable number.  */ epsilon ( ) { return super . epsilon ( ) ; } }