| 307 | } |
| 308 | |
| 309 | void evalNodes(vector<Param>& outputs, const vector<Node*>& output_nodes) { |
| 310 | const unsigned nrOutputs{static_cast<unsigned>(outputs.size())}; |
| 311 | if (nrOutputs == 0) { return; } |
| 312 | assert(outputs.size() == output_nodes.size()); |
| 313 | KParam& out_info{outputs[0].info}; |
| 314 | dim_t* outDims{out_info.dims}; |
| 315 | dim_t* outStrides{out_info.strides}; |
| 316 | #ifndef NDEBUG |
| 317 | for_each(begin(outputs)++, end(outputs), |
| 318 | [outDims, outStrides](Param& output) { |
| 319 | assert(equal(output.info.dims, output.info.dims + AF_MAX_DIMS, |
| 320 | outDims) && |
| 321 | equal(output.info.strides, |
| 322 | output.info.strides + AF_MAX_DIMS, outStrides)); |
| 323 | }); |
| 324 | #endif |
| 325 | |
| 326 | dim_t ndims{outDims[3] > 1 ? 4 |
| 327 | : outDims[2] > 1 ? 3 |
| 328 | : outDims[1] > 1 ? 2 |
| 329 | : outDims[0] > 0 ? 1 |
| 330 | : 0}; |
| 331 | bool is_linear{true}; |
| 332 | dim_t numOutElems{1}; |
| 333 | for (dim_t dim{0}; dim < ndims; ++dim) { |
| 334 | is_linear &= (numOutElems == outStrides[dim]); |
| 335 | numOutElems *= outDims[dim]; |
| 336 | } |
| 337 | if (numOutElems == 0) { return; } |
| 338 | |
| 339 | // Use thread local to reuse the memory every time you are here. |
| 340 | thread_local Node_map_t nodes; |
| 341 | thread_local vector<Node*> full_nodes; |
| 342 | thread_local vector<Node_ids> full_ids; |
| 343 | thread_local vector<int> output_ids; |
| 344 | |
| 345 | // Reserve some space to improve performance at smaller sizes |
| 346 | constexpr size_t CAP{1024}; |
| 347 | if (full_nodes.capacity() < CAP) { |
| 348 | nodes.reserve(CAP); |
| 349 | output_ids.reserve(10); |
| 350 | full_nodes.reserve(CAP); |
| 351 | full_ids.reserve(CAP); |
| 352 | } |
| 353 | |
| 354 | const af::dtype outputType{output_nodes[0]->getType()}; |
| 355 | const size_t outputSizeofType{size_of(outputType)}; |
| 356 | for (Node* node : output_nodes) { |
| 357 | assert(node->getType() == outputType); |
| 358 | const int id{node->getNodesMap(nodes, full_nodes, full_ids)}; |
| 359 | output_ids.push_back(id); |
| 360 | } |
| 361 | |
| 362 | const size_t outputSize{numOutElems * outputSizeofType * nrOutputs}; |
| 363 | size_t inputSize{0}; |
| 364 | unsigned nrInputs{0}; |
| 365 | bool moddimsFound{false}; |
| 366 | for (const Node* node : full_nodes) { |
no test coverage detected