def feed_input(self, ref, data, layout=""): """Bind the NumPy array to a tensor produced by ExternalSource operator. It is worth mentioning that `ref` should not be overridden with other operator outputs.""" if not self._built: raise RuntimeError("Pipeline must be built first.") Edge._validate_edge_reference(ref) if isinstance(data, list): if self._batch_size != len(data): raise RuntimeError( "Data list provided to feed_input needs to have batch_size length" ) inputs = [] for datum in data: inputs.append(Tensors.TensorCPU(datum, layout)) self._pipe.SetExternalTensorInput(ref.name, inputs) else: inp = Tensors.TensorListCPU(data, layout) self._pipe.SetExternalTLInput(ref.name, inp)
def _prepare_graph(self): self._pipe = b.Pipeline( self._batch_size, self._num_threads, self._device_id, self._seed, self._exec_pipelined, self._prefetch_queue_depth, self._exec_async, self._bytes_per_sample, self._set_affinity, self._max_streams, self._default_cuda_stream_priority) self._pipe.SetExecutionTypes(self._exec_pipelined, self._exec_separated, self._exec_async) self._pipe.SetQueueSizes(self._cpu_queue_size, self._gpu_queue_size) prev_pipeline = Pipeline.set_current(self) outputs = self.define_graph() Pipeline.set_current(prev_pipeline) if (not isinstance(outputs, tuple) and not isinstance(outputs, list)): outputs = (outputs, ) for output in outputs: Edge._validate_edge_reference(output) # Backtrack to construct the graph op_ids = set() edges = deque(list(outputs) + self._sinks) ops = [] while edges: current_edge = edges.popleft() source_op = current_edge.source if source_op is None: raise RuntimeError("Pipeline encountered " "Edge with no source op.") # To make sure we don't double count ops in # the case that they produce more than one # output, we keep track of the unique op ids # for each op we encounter and only add the # op if we have not already if source_op.id not in op_ids: op_ids.add(source_op.id) source_op.check_args() ops.append(source_op) else: # If the op was already added, we need to # change its position to the top of the list. # This ensures topological ordering of ops # when adding to the backend pipeline ops.remove(source_op) ops.append(source_op) for edge in source_op.inputs: if isinstance(edge, list): for e in edge: edges.append(e) else: edges.append(edge) # Add the ops to the graph and build the backend related_logical_id = {} while ops: op = ops.pop() if op.relation_id not in related_logical_id: related_logical_id[op.relation_id] = self._pipe.AddOperator( op.spec, op.name) else: self._pipe.AddOperator(op.spec, op.name, related_logical_id[op.relation_id]) self._prepared = True self._names_and_devices = [(e.name, e.device) for e in outputs]