(
fetches: SymbolicTensor|SymbolicTensor[], feedDict: FeedDict,
kwargs?: Kwargs, probe?: ExecutionProbe)
| 243 | * encountered during the execution lacks a feed value in `feedDict`. |
| 244 | */ |
| 245 | export function execute( |
| 246 | fetches: SymbolicTensor|SymbolicTensor[], feedDict: FeedDict, |
| 247 | kwargs?: Kwargs, probe?: ExecutionProbe): Tensor| |
| 248 | Tensor[]|[Tensor | Tensor[]] { |
| 249 | const training: boolean = kwargs == null ? false : kwargs['training']; |
| 250 | |
| 251 | const arrayFetches = Array.isArray(fetches); |
| 252 | const fetchArray: SymbolicTensor[] = |
| 253 | arrayFetches ? fetches : [fetches]; |
| 254 | |
| 255 | const outputNames = fetchArray.map(t => t.name); |
| 256 | const finalOutputs: Tensor[] = []; |
| 257 | const feedNames = feedDict.names(); |
| 258 | for (const outputName of outputNames) { |
| 259 | if (feedNames.indexOf(outputName) !== -1) { |
| 260 | finalOutputs.push(feedDict.getValue(outputName)); |
| 261 | } else { |
| 262 | finalOutputs.push(null); |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | if (probe != null) { |
| 267 | // For optional probing of memory footprint during execution. |
| 268 | probe.maxNumTensors = -Infinity; |
| 269 | probe.minNumTensors = Infinity; |
| 270 | } |
| 271 | |
| 272 | // Check cache. |
| 273 | const fetchAndFeedKey = |
| 274 | outputNames.join(',') + '|' + feedDict.names().sort().join(','); |
| 275 | let sorted: SymbolicTensor[] = cachedSorted.get(fetchAndFeedKey); |
| 276 | let recipientCounts: {[fetchName: string]: number}; |
| 277 | if (sorted == null) { |
| 278 | // Cache doesn't contain the desired combination of fetches. Compute |
| 279 | // topological sort for the combination for the first time. |
| 280 | const out = getTopologicalSortAndRecipientCounts(fetchArray, feedDict); |
| 281 | sorted = out.sorted; |
| 282 | recipientCounts = out.recipientCounts; |
| 283 | |
| 284 | // Store results in cache for future use. |
| 285 | cachedSorted.put(fetchAndFeedKey, sorted); |
| 286 | cachedRecipientCounts.put(fetchAndFeedKey, recipientCounts); |
| 287 | } |
| 288 | recipientCounts = {}; |
| 289 | if (!training) { |
| 290 | Object.assign(recipientCounts, cachedRecipientCounts.get(fetchAndFeedKey)); |
| 291 | } |
| 292 | |
| 293 | const internalFeedDict = new FeedDict(feedDict); |
| 294 | |
| 295 | // Start iterative execution on the topologically-sorted SymbolicTensors. |
| 296 | for (let i = 0; i < sorted.length; ++i) { |
| 297 | if (probe != null) { |
| 298 | // For optional probing of memory usage during execution. |
| 299 | const numTensors = memory().numTensors; |
| 300 | if (numTensors > probe.maxNumTensors) { |
| 301 | probe.maxNumTensors = numTensors; |
| 302 | } |
no test coverage detected
searching dependent graphs…