| 174 | } |
| 175 | |
| 176 | void split_reduce::apply(module_pass_manager& mpm) const |
| 177 | { |
| 178 | for(auto ins : iterator_for(mpm.get_module())) |
| 179 | { |
| 180 | if(ins->name() != "fused_reduce") |
| 181 | continue; |
| 182 | auto* rm = ins->module_inputs().front(); |
| 183 | if(get_reduce_size(rm) < split_size) |
| 184 | continue; |
| 185 | splitter s{rm}; |
| 186 | auto splits = s.find_splits(); |
| 187 | if(splits.empty()) |
| 188 | continue; |
| 189 | // Only use split reduce with float for now |
| 190 | // TODO: Support other data types |
| 191 | if(not std::all_of(splits.begin(), splits.end(), [](instruction_ref split) { |
| 192 | return contains({shape::float_type, shape::half_type}, split->get_shape().type()); |
| 193 | })) |
| 194 | continue; |
| 195 | auto v = ins->get_operator().to_value(); |
| 196 | auto axes = v["axes"].to_vector<std::int64_t>(); |
| 197 | |
| 198 | auto alive = s.find_alive(splits); |
| 199 | |
| 200 | std::array<module::with_inputs, 2> mods; |
| 201 | if(not alive.empty()) |
| 202 | { |
| 203 | auto mods3 = rm->split(ins->inputs(), alive, splits); |
| 204 | auto r = insert_module_inline(mpm.get_module(), ins, mods3[0]); |
| 205 | mods3[1].replace(alive, r); |
| 206 | mods3[2].replace(alive, r); |
| 207 | mods = {std::move(mods3[1]), std::move(mods3[2])}; |
| 208 | } |
| 209 | else |
| 210 | { |
| 211 | mods = rm->split(ins->inputs(), splits); |
| 212 | } |
| 213 | |
| 214 | auto* splitm = mpm.create_module(rm->name() + "_split", std::move(mods[0].mod)); |
| 215 | splitm->set_bypass(); |
| 216 | |
| 217 | // Insert split reduce |
| 218 | auto split_reduce = mpm.get_module().insert_instruction( |
| 219 | ins, |
| 220 | make_op("split_fused_reduce", {{"axes", axes}, {"assign", assign_op(splits)}}), |
| 221 | mods[0].inputs, |
| 222 | {splitm}); |
| 223 | |
| 224 | std::vector<instruction_ref> split_reduce_each; |
| 225 | if(splits.size() == 1) |
| 226 | { |
| 227 | split_reduce_each = {split_reduce}; |
| 228 | } |
| 229 | else |
| 230 | { |
| 231 | transform(range(splits.size()), std::back_inserter(split_reduce_each), [&](auto i) { |
| 232 | return mpm.get_module().insert_instruction( |
| 233 | ins, make_op("get_tuple_elem", {{"index", i}}), split_reduce); |
nothing calls this directly
no test coverage detected