class TensorStream::Evaluator::RubyEvaluator
PURE ruby evaluator used for testing and development
Attributes
retain[RW]
Public Class Methods
get_storage_manager()
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 48 def self.get_storage_manager RubyStorageManager.current_storage_manager end
Public Instance Methods
complete_eval(tensor, context)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 76 def complete_eval(tensor, context) Kernel.loop do old_tensor = tensor tensor = run(tensor, context) tensor = tensor.map { |t| complete_eval(t, context) } if tensor.is_a?(Array) && !tensor.empty? && tensor[0].is_a?(Tensor) break if old_tensor.equal?(tensor) break unless tensor.is_a?(Tensor) end tensor.is_a?(OutputGroup) ? tensor.outputs : tensor end
run(tensor, execution_context)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 52 def run(tensor, execution_context) return tensor.map { |t| run(t, execution_context) } if tensor.is_a?(Array) && !tensor.empty? && tensor[0].is_a?(Tensor) tensor = tensor.call if tensor.is_a?(Proc) child_context = execution_context.dup res = if tensor.is_a?(Operation) eval_operation(tensor, child_context) elsif !tensor.is_a?(Tensor) tensor else tensor.op end execution_context.deep_merge!(returns: child_context[:returns]) res end
run_with_buffer(tensor, context, execution_context)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 69 def run_with_buffer(tensor, context, execution_context) @context = context @context[:_cache][:_cl_buffers] ||= {} if context[:_cache] result = run(tensor, execution_context) TensorStream::Buffer.new(data_type: tensor.data_type, buffer: result) end
Protected Instance Methods
convert_from_buffer(_tensor, result)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 280 def convert_from_buffer(_tensor, result) result.buffer end
eval_operation(tensor, child_context)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 240 def eval_operation(tensor, child_context) return @context[tensor.name] if @context.key?(tensor.name) # puts "ruby eval #{tensor.operation} -> #{object_id}: #{tensor.name}" invoke(tensor, child_context).tap do |result| # puts "result done ruby #{object_id}: #{tensor.name}" # assertions to make sure inferred shapes == actual evaluated shapes if tensor.shape.known? && (result.is_a?(Array) || result.is_a?(Float) || result.is_a?(Integer)) raise "assert error #{tensor.name} #{shape_eval(result)} != #{tensor.shape.shape}" if shape_eval(result) != tensor.shape.shape end if tensor.breakpoint a = tensor.inputs[0] if tensor.inputs && tensor.inputs[0] b = tensor.inputs[1] if tensor.inputs && tensor.inputs[1] a = complete_eval(a, child_context) b = complete_eval(b, child_context) tensor.breakpoint.call(tensor, a, b, complete_eval(result, child_context)) end if @log_intermediates @context[:compute_history] << { name: tensor.name, type: tensor.data_type, shape: shape_eval(result), source: tensor.source, description: tensor.to_math(true, 1), value: result, } end @context[tensor.name] = result end rescue EvaluatorExcecutionException => e raise e, "error #{e.message} while evaluating #{tensor.name} defined at #{tensor.source}" rescue TensorStreamError => e raise e, "error #{e.message} while evaluating #{tensor.name} defined at #{tensor.source}" rescue StandardError => e puts e.message puts e.backtrace.join("\n") raise EvaluatorExcecutionException.new(e, tensor), "error #{e.message} while evaluating #{tensor.name} : #{tensor.to_math(true, 1)} defined at #{tensor.source}" end
prepare_input(tensor, context, options = {})
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 104 def prepare_input(tensor, context, options = {}) return nil unless tensor if options[:noop] tensor elsif options[:no_eval] run(tensor, context) else complete_eval(tensor, context) end end
var_assign_value(tensor, value)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 97 def var_assign_value(tensor, value) @storage_manager ||= TensorStream::RubyStorageManager.current_storage_manager @storage_manager.assign_value(tensor.graph, tensor.options[:var_name] || tensor.name, value) value end
var_read_value(tensor)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 92 def var_read_value(tensor) @storage_manager ||= TensorStream::RubyStorageManager.current_storage_manager @storage_manager.read_value(tensor.graph, tensor.options[:var_name]) end
Private Instance Methods
_get_randomizer(tensor, seed)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 412 def _get_randomizer(tensor, seed) if tensor.graph.random_seed && seed Random.new(tensor.graph.random_seed ^ seed) elsif tensor.graph.random_seed @session.randomizer[tensor.graph.object_id] ||= Random.new(tensor.graph.random_seed) @session.randomizer[tensor.graph.object_id] elsif seed @session.randomizer[tensor.operation] ||= Random.new(seed) @session.randomizer[tensor.operation] else Random.new end end
_rank_from_shape(shape)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 344 def _rank_from_shape(shape) shape.is_a?(Array) ? shape.size : 0 end
all_true?(arr)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 383 def all_true?(arr) if arr.is_a?(Array) arr.each do |a| return false unless all_true?(a) end return true end !!arr end
call_3way_vector_op(v_a, v_b, v_c, child_context) { |v_a, v_b, v_c| ... }
click to toggle source
handle 3 tensor math operations
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 369 def call_3way_vector_op(v_a, v_b, v_c, child_context, &block) return yield(v_a, v_b, v_c) unless v_a.is_a?(Array) v_a.each_with_index.collect do |v1, index| v2 = v_b[index] v3 = v_c.is_a?(Array) ? v_c[index] : v_c if v1.is_a?(Array) call_3way_vector_op(v1, v2, v3, child_context, &block) else yield(v1, v2, v3) end end end
call_op(a, child_context, &block)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 300 def call_op(a, child_context, &block) a = complete_eval(a, child_context) process_function_op(a, &block) end
call_vector_op(tensor, op, a, b, child_context, &block)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 305 def call_vector_op(tensor, op, a, b, child_context, &block) process_vector_math_op(tensor, a, b, child_context, &block) rescue FullEvalNotPossible TensorStream.send(op.to_sym, a, b) end
concat(a, b, axis)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 358 def concat(a, b, axis) if axis.zero? a + b else a.each_with_index.collect do |i, index| concat(i, b[index], axis - 1) end end end
concat_array(values, axis)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 348 def concat_array(values, axis) combined_array = values.shift axis = get_rank(combined_array) - 1 if axis == -1 values.each do |v| combined_array = concat(combined_array, v, axis) end combined_array end
dump_intermediates()
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 426 def dump_intermediates arr = [] arr << "============== start ===================" @context[:compute_history].each_with_index do |history, _index| arr << "------------------------------------" arr << history[:name] arr << "#{history[:type]} #{history[:shape]}" arr << history[:source] arr << history[:description] arr << "" arr << history[:value].to_json arr << "------------------------------------" end arr << "============== end =====================" str = arr.join("\n") File.write("/tmp/intermediates.txt", str) end
generate_vector(shape, dtype: :float32, generator:)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 394 def generate_vector(shape, dtype: :float32, generator:) if shape.is_a?(Integer) Array.new(shape) do generator.call end elsif shape.size > 1 Array.new(shape[0]) do generate_vector(shape[1..shape.size], generator: generator, dtype: dtype) end elsif shape.size == 1 Array.new(shape[0]) do generator.call end elsif shape.size.zero? generator.call end end
get_op_with_axis(a, target_axis, current_axis, op)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 286 def get_op_with_axis(a, target_axis, current_axis, op) rank = get_rank(a) return a.send(:"#{op}_index") if rank == 1 if current_axis == target_axis compare_items = a.collect(&:flatten).transpose compare_items.map { |item| item.index(item.send(:"#{op}")) } elsif a[0].is_a?(Array) a.map { |item| get_op_with_axis(item, target_axis, current_axis + 1, op) } else return a.send(:"#{op}_index") end end
multi_array_op(func, *args)
click to toggle source
multi array ops on ruby arrays with same sizes
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 332 def multi_array_op(func, *args) elem = args[0] if elem.is_a?(Array) elem.each_with_index.collect do |_item, index| indexed_args = args.collect { |a| a = a.is_a?(Array) ? a : [a]; a[index] } multi_array_op(func, *indexed_args) end else func.call(*args) end end
process_vector_math_op(tensor, a, b, child_context, &block)
click to toggle source
# File lib/tensor_stream/evaluator/ruby_evaluator.rb, line 311 def process_vector_math_op(tensor, a, b, child_context, &block) eval_a = global_eval(tensor, a, child_context) unless a.nil? eval_b = global_eval(tensor, b, child_context) unless b.nil? raise FullEvalNotPossible.new, "full eval not possible for #{a.name}" if eval_a.is_a?(Tensor) || eval_b.is_a?(Tensor) # ruby scalar eval_a, eval_b = broadcast(eval_a, eval_b) vector_op(eval_a, eval_b, &block) # if get_rank(eval_a).zero? # if get_rank(eval_b).zero? # op.call(eval_a, eval_b) # else # vector_op(eval_b, eval_a, op, true) # end # else # vector_op(eval_a, eval_b, op) # end end