Module: CArray::Fusion
- Defined in:
- lib/carray/fusion.rb
Defined Under Namespace
Classes: Const, Leaf, Op, Plan, Refused, Walk
Constant Summary collapse
- LAZY_CLASSES =
[CAMonOp, CABinOp, CATriOp, CAMonCmp, CABinCmp, CALazyMarker]
- BINOP_NAMES =
A lazy node names its operation by an id and the kernels name it by a symbol. These are the same operations, spelled the way each side spells them; the rest are spelled alike.
{ :+ => :add, :- => :sub, :* => :mul, :/ => :div, :** => :power, :% => :mod, :& => :bit_and_i, :| => :bit_or_i, :^ => :bit_xor_i, :<< => :bit_lshift, :>> => :bit_rshift, }.freeze
- TRIOP_NAMES =
{ :__clip_ki__ => :clip }.freeze
- MONOP_BY_ID =
CArray::LAZY_MONOP_OP_IDS.invert.freeze
- BINOP_BY_ID =
CArray::LAZY_BINOP_OP_IDS.invert.freeze
- TRIOP_BY_ID =
CArray::LAZY_TRIOP_OP_IDS.invert.freeze
- TRAPPING =
Integer division and its relatives raise on a zero divisor, so a cell the mask excludes must not be computed at all -- the divisor there is nobody's business (ca_binop_dispatch.c).
%i[div mod quo_i fmod].freeze
- INTEGERS =
%i[int8 int16 int32 int64 uint8 uint16 uint32 uint64].freeze
- THRESHOLD =
Reaching a compiled kernel costs about the same whatever the array's size, and what it buys is the passes the walk would make. Below this the walk is the faster answer. The crossing moves with how wide the expression is -- measured, thirty thousand cells at one operation, six thousand at six -- and this brackets those: a one-operation expression loses a couple of microseconds here, a six-operation one wins ten.
10_000
Class Method Summary collapse
- .askable?(view) ⇒ Boolean
- .build(view) ⇒ Object
-
.evaluate(view) ⇒ Object
Returns the array, or nil where nothing computed it.
-
.evaluate_into(view, out) ⇒ Object
Fills an array the caller already has.
- .lazy?(x) ⇒ Boolean
-
.plan(view) ⇒ Object
Returns a Plan, or nil where the expression holds something a plan cannot describe.
Class Method Details
.askable?(view) ⇒ Boolean
102 103 104 |
# File 'lib/carray/fusion.rb', line 102 def self.askable? (view) ! CArray.expression_evaluator.nil? && view.elements >= THRESHOLD end |
.build(view) ⇒ Object
114 115 116 117 118 119 120 |
# File 'lib/carray/fusion.rb', line 114 def self.build (view) raise Refused, "not a lazy expression" unless lazy?(view) w = Walk.new w.visit(view) Plan.new(w.nodes, w.leaves, view.data_type, view.dim, w.leaves.any? { |a| a.has_mask? }, w.signature) end |
.evaluate(view) ⇒ Object
Returns the array, or nil where nothing computed it.
76 77 78 79 80 |
# File 'lib/carray/fusion.rb', line 76 def self.evaluate (view) return nil unless askable?(view) out = CArray.__alloc_uninit__(view.data_type, view.dim) evaluate_into(view, out) ? out : nil end |
.evaluate_into(view, out) ⇒ Object
Fills an array the caller already has. Called from the store as well, where making one and copying it over would be most of the work. Returns true when something computed it.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/carray/fusion.rb', line 85 def self.evaluate_into (view, out) evaluator = CArray.expression_evaluator or return false return false unless askable?(view) plan = plan(view) or return false # A marker over an array, or anything else with nothing to compute, # is not worth handing over. return false unless plan.nodes.any? { |n| n.is_a?(Op) } out.mask = 0 if plan.masked && ! out.has_mask? evaluator.call(plan, out) ? true : false rescue StandardError => error CArray.expression_evaluator = nil warn "CArray: the registered expression evaluator raised " \ "(#{error.class}: #{error.}); expressions will be walked " \ "from here on" false end |
.lazy?(x) ⇒ Boolean
122 123 124 |
# File 'lib/carray/fusion.rb', line 122 def self.lazy? (x) LAZY_CLASSES.any? { |k| x.is_a?(k) } end |
.plan(view) ⇒ Object
Returns a Plan, or nil where the expression holds something a plan cannot describe. Refusing is ordinary: the caller walks instead.
108 109 110 111 112 |
# File 'lib/carray/fusion.rb', line 108 def self.plan (view) build(view) rescue Refused nil end |