From cff9149ece0b5c8501e5e584019b27a379955228 Mon Sep 17 00:00:00 2001 From: Fabian Gruber <fabian.gruber@inria.fr> Date: Mon, 16 Apr 2018 14:41:24 -0600 Subject: [PATCH] added prose description of the ILP model implemented in Gurobi. --- src/pipedream/ilp/the-ilp-model.txt | 164 ++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/pipedream/ilp/the-ilp-model.txt diff --git a/src/pipedream/ilp/the-ilp-model.txt b/src/pipedream/ilp/the-ilp-model.txt new file mode 100644 index 0000000..18aaaf3 --- /dev/null +++ b/src/pipedream/ilp/the-ilp-model.txt @@ -0,0 +1,164 @@ +///############################################################################# +///##### INPUT + +///### CPU LAYOUT + +/// number of instructions (each is identified by an opaque int) +int num_insts = ...; + +/// number of muops (each is identified by an opaque int) +int num_muops = ...; + +/// number of ports (each is identified by an opaque int) +int num_ports = ...; + + +///### KERNELS + +/// number of kernels that where run +int num_kernels = ...; + +/// Instruction per Cycle (IPC), i.e. throughput, measured for kernel *k* +float IPC[k in num_kernels] = ...; + +/// how many times instruction *i* appears in kernel *k* +int occurences[k in num_kernels][i in num_insts] = ...; + + +///############################################################################# +///##### OUTPUT + +/// bipartite graph between instructions and muops +dvar int graph_im[num_muops][num_ports] in 0..1; + +/// bipartite graph between muops and ports +dvar int graph_mp[num_muops][num_ports] in 0..1; + + +///############################################################################# +///##### HELPERS + +/// throughput per edge (inst, muop) in kernel k +dvar float throughput_im[num_kernels][num_insts][num_muops]; + +/// throughput per edge (muop, port) in kernel k +dvar float throughput_mp[num_kernels][num_insts][num_muops]; + +/// throughput for muop type i in kernel s +dexpr float muop_throughput[k in num_kernels][m in num_muops] = sum(p in num_ports) throughput[k][m][p]; + +/// mean throughput for a given muop type in a kernel +dexpr float mean[k in num_kernels][m in num_muops] = (1 / num_ports) * sum(p in num_ports) throughput[k][m][p]; + +/// variance of throughput for a given muop type in a kernel +dexpr float variance[k in num_kernels][m in num_muops] = (1 / num_ports) * + sum(p in num_ports) pow(throughput[k][m][p], 2) - pow(mean[k][m], 2); + + +dexpr int num_im_edges = sum(k in num_kernels) sum(i in num_insts) sum(m in num_muops) delta_mp[k][i][m] + +dexpr int num_mp_edges = sum(k in num_kernels) sum(m in num_muops) sum(p in num_ports) delta_mp[k][m][p] + + +//############################################################################## +//##### OBJECTIVE FUNCTION + +dexpr float all_throughputs = sum(k in num_kernels) total_throughput[k]; + +/// number of edges present in the machine +dexpr float num_edges = sum(i in Src, p in num_ports) delta_mp[m][p]; + +dexpr float all_variances = sum(k in num_kernels, i in Src) variance[k][m]; + +maximize(num_mp_edges - num_im_edges); + + +//############################################################################## +//##### CONSTRAINTS + +subject to { + forall(k in num_kernels, i in Src, p in num_ports) { + throughput_bounds: + 0 <= throughput[k][m][p]; + } + forall(k in num_kernels, i in Src, p in num_ports) { + throughputs_limited_by_delta_mp: + throughput[k][m][p] <= delta_mp[m][p]; + } + + forall(k in num_kernels, p in num_ports) { + port_bandwidth: + sum(i in Src) throughput[k][m][p] <= 1; + } + + forall(k in num_kernels) { + total_throughput_limited_by_ports: + total_throughput[k] <= num_ports; + } + + forall(k in num_kernels) { + total_throughput_is_sum_of_throughputss: + total_throughput[k] == sum(i in Src) muop_throughput[k][m]; + } + +#// prints constraints set with OPL label iff constraint text is not empty +#% macro constraint_set(name) +#% set X = caller().strip() +#% if X and not X.isspace() + {{ name }}: + {{ X }} +#% endif +#% endmacro + +#// print delta_mp +#% call constraint_set('port_layout') +#% for i, j in model.delta_mp | sort_by_index +#% set edge = model.delta_mp[i, j] +#% if edge.is_specified + delta_mp[{{ i | tuple }}][{{ j | tuple }}] == {{ edge }}; +#% endif +#% endfor +#% endcall + +#// print total throughput per kernel +#% call constraint_set('observed_total_throughput') +#% for seq in model.total_throughput | sort_by_index +#% set total_throughput = model.total_throughput[seq] +#% if total_throughput.is_specified + total_throughput[{{ seq[0] | tuple }}] == {{ total_throughput }}; +#% endif +#% endfor +#% endcall + +#// print throughput per muop/port pair +#% call constraint_set('observed_throughputs') +#% for s, i, j in model.throughput | sort_by_index +#% set throughput = model.throughput[s, i, j] +#% if throughput.is_specified + throughput[{{ s | tuple }}][{{ i | tuple }}][{{ j | tuple }}] == {{ throughput }}; +#% endif +#% endfor +#% endcall + +#// print instruction ratios in kernels +#% call constraint_set('inst_mix') +#% set mix = model.instruction_mix +#% for s, i in mix +#% set ratio = mix[s, i] +#% if ratio == 0 + #// can't use muop_throughput here because that would use tuple patterns + #// and we already use non-pattern constraints elsewhere + sum(p in num_ports) throughput[{{ s | tuple }}][{{ i | tuple }}][p] == 0; +#% endif +#% endfor +#% for s in model.kernels +#% for i1, i2 in model.muops | combinations(2) +#% set r1 = mix[s, i1] +#% set r2 = mix[s, i2] +#% if r1 and r2 + {{ r1 }} * sum(p in num_ports) throughput[{{ s | tuple }}][{{ i1 | tuple }}][p] == {{ r2 }} * sum(p in num_ports) throughput[{{ s | tuple }}][{{ i2 | tuple }}][p]; +#% endif +#% endfor +#% endfor +#% endcall +} -- GitLab