| 72 | int detail::RetainGraph::tracing_counter{0}; |
| 73 | |
| 74 | array eval_impl(std::vector<array> outputs, bool async) { |
| 75 | std::deque<array> tape; |
| 76 | |
| 77 | // Make an effort to choose a good output stream |
| 78 | Stream stream = default_stream(default_device()); |
| 79 | for (auto& o : outputs) { |
| 80 | if (o.status() == array::Status::unscheduled && o.has_primitive()) { |
| 81 | stream = o.primitive().stream(); |
| 82 | break; |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | // Map of array id that needs fence and stream it's computed on |
| 87 | std::unordered_map<uintptr_t, std::pair<uint32_t, bool>> needs_fence; |
| 88 | |
| 89 | auto synchronizer = array( |
| 90 | {}, bool_, std::make_shared<Synchronizer>(stream), std::move(outputs)); |
| 91 | |
| 92 | // Stream fences for inter-stream synchronization |
| 93 | std::unordered_map<uint32_t, Fence> fences; |
| 94 | |
| 95 | // Stream events for synchronization after eval |
| 96 | std::unordered_map<uint32_t, Event> events; |
| 97 | { |
| 98 | auto e = Event{stream}; |
| 99 | e.set_value(1); |
| 100 | synchronizer.attach_event(e); |
| 101 | events.emplace(stream.index, std::move(e)); |
| 102 | } |
| 103 | |
| 104 | { |
| 105 | // Record the degree of each input |
| 106 | std::unordered_map<std::uintptr_t, int> cache; |
| 107 | |
| 108 | std::stack<std::pair<std::reference_wrapper<array>, int>> dfs; |
| 109 | dfs.emplace(synchronizer, 0); |
| 110 | while (!dfs.empty()) { |
| 111 | auto& [a_ref, idx] = dfs.top(); |
| 112 | auto& a = a_ref.get(); |
| 113 | |
| 114 | if (idx < a.inputs().size()) { |
| 115 | // Add an input, and continue |
| 116 | auto& in = a.inputs()[idx++]; |
| 117 | |
| 118 | if (in.status() == array::Status::unscheduled) { |
| 119 | if (async && in.is_tracer()) { |
| 120 | throw std::invalid_argument( |
| 121 | "[async_eval] Not allowed inside a graph transformation."); |
| 122 | } |
| 123 | if (!in.has_primitive()) { |
| 124 | if (in.is_tracer()) { |
| 125 | throw std::invalid_argument( |
| 126 | "[eval] Attempting to eval an array during function" |
| 127 | " transformations like compile or vmap is not allowed."); |
| 128 | } |
| 129 | throw std::runtime_error( |
| 130 | "[eval] Attempting to eval an array without a primitive.\n" |
| 131 | "If you are compiling a function, make sure all the inputs " |
no test coverage detected