PROFILE ALL THE THINGS! (well, not gift wrapper, cause it sucks.. but almost all the things!)

This commit is contained in:
Casper 2018-10-21 18:08:38 +02:00
parent b6dadc7789
commit 6a44176cdf
No known key found for this signature in database
GPG Key ID: B1156723DB3BDDA8
3 changed files with 96 additions and 34 deletions

View File

@ -28,18 +28,17 @@ def graham_scan(points):
sorted_points = sorted(points) sorted_points = sorted(points)
UH = sorted_points[:2] UH = sorted_points[:2]
with Profiler("iterating upper hull", excluded=("calculating sidedness",)): with Profiler("iterating points", excluded=("calculating sidedness",)):
for s in sorted_points[2:]: for s in sorted_points[2:]:
while len(UH) > 1 and (sidedness(UH[-2], UH[-1], s) != Side.ABOVE): while len(UH) > 1 and (sidedness(UH[-2], UH[-1], s) != Side.ABOVE):
del UH[-1] del UH[-1]
UH.append(s) UH.append(s)
with Profiler("reversing list"):
reversed_list = list(reversed(sorted_points)) reversed_list = list(reversed(sorted_points))
reversed_list.append(UH[0]) reversed_list.append(UH[0])
LH = reversed_list[:2] LH = reversed_list[:2]
with Profiler("iterating lower hull", excluded=("calculating sidedness",)): with Profiler("iterating points", excluded=("calculating sidedness",)):
for s in reversed_list[2:]: for s in reversed_list[2:]:
while len(LH) > 1 and (sidedness(LH[-2], LH[-1], s) != Side.ABOVE): while len(LH) > 1 and (sidedness(LH[-2], LH[-1], s) != Side.ABOVE):
del LH[-1] del LH[-1]

View File

@ -10,6 +10,9 @@ from profile import Profiler
from quick_hull import quick_hull from quick_hull import quick_hull
import os.path import os.path
import matplotlib.pyplot as plt
#random.seed(1337_420) #random.seed(1337_420)
TimedResult = namedtuple("TimedResult", "algorithm points running_time") TimedResult = namedtuple("TimedResult", "algorithm points running_time")
@ -96,9 +99,9 @@ def do_one_profile(num_points):
points = {util.gen_point(0, 100) for _ in range(num_points)} points = {util.gen_point(0, 100) for _ in range(num_points)}
tests = [ tests = [
#("graham_scan", graham_scan), ("graham_scan", graham_scan),
#("gift_wrapper", rapper), #("gift_wrapper", rapper),
#("quick_hull", quick_hull), ("quick_hull", quick_hull),
("mbc", mbc), ("mbc", mbc),
("mbc2", mbc2), ("mbc2", mbc2),
("mbc_no_shuffle", mbc_no_shuffle), ("mbc_no_shuffle", mbc_no_shuffle),
@ -135,38 +138,94 @@ def do_one_profile(num_points):
return results return results
def do_profile(): def plot_mbc(results, ax):
num_points = 60_000
#results = do_one_profile(num_points)
results = {"mbc": {"times": {"finding median": 0.006870746612548828, "partitioning set": 0.066436767578125, "flipping constraints": 0.13354206085205078, "shuffling constraints": 0.08272123336791992, "solving LP": 0.13545918464660645, "finding bridge points": 0.06052136421203613, "pruning between line points": 0.04519915580749512, "mbc": 0.5643129348754883, "other": 0.033562421798706055}, "total": 0.5643129348754883, "total_profiled": 0.5307505130767822, "unaccounted": 0.033562421798706055}, "mbc2": {"times": {"extra pruning step": 0.15866398811340332, "finding median": 0.00189971923828125, "partitioning set": 0.022511959075927734, "flipping constraints": 0.04117441177368164, "shuffling constraints": 0.030447006225585938, "solving LP": 0.05805325508117676, "finding bridge points": 0.025882959365844727, "pruning between line points": 0.014936208724975586, "mbc2": 0.3658268451690674, "other": 0.01225733757019043}, "total": 0.3658268451690674, "total_profiled": 0.35356950759887695, "unaccounted": 0.01225733757019043}, "mbc_no_shuffle": {"times": {"finding median": 0.006849050521850586, "partitioning set": 0.06539726257324219, "flipping constraints": 0.13605880737304688, "solving LP": 0.06955385208129883, "finding bridge points": 0.06419634819030762, "pruning between line points": 0.044390201568603516, "mbc_no_shuffle": 0.397723913192749, "other": 0.011278390884399414}, "total": 0.397723913192749, "total_profiled": 0.3864455223083496, "unaccounted": 0.011278390884399414}, "mbc2_no_shuffle": {"times": {"extra pruning step": 0.16416001319885254, "finding median": 0.002000570297241211, "partitioning set": 0.022954702377319336, "flipping constraints": 0.0455164909362793, "solving LP": 0.02709197998046875, "finding bridge points": 0.022936582565307617, "pruning between line points": 0.017188310623168945, "mbc2_no_shuffle": 0.30688953399658203, "other": 0.005040884017944336}, "total": 0.30688953399658203, "total_profiled": 0.3018486499786377, "unaccounted": 0.005040884017944336}}
print("================== RESULTS ==================")
print(json.dumps(results))
algorithms = list(results.keys()) algorithms = list(results.keys())
steps = ( steps = (
"other", "other",
"finding median", "finding median",
"partitioning set", "partitioning set",
"flipping constraints", "flipping constraints",
"solving 2D", "solving LP",
"finding bridge points", "finding bridge points",
"pruning between line points", "pruning between line points",
"shuffling constraints", "shuffling constraints",
"extra pruning step", "extra pruning step",
) )
util.stacked_bar(ax=ax,
data = [[result["times"].get(step, 0) * 1000 for result in results.values()] data=[[result["times"].get(step, 0) * 1000 for result in results.values()] for step in steps],
for step in steps]
util.stacked_bar(data=data,
series_labels=steps, series_labels=steps,
category_labels=algorithms, category_labels=algorithms,
show_values=True, value_format="{:.1f}")
value_format="{:.1f}",
y_label="time (ms)",
grid=False, def plot_graham(result, ax):
reverse=False) steps = (
"other",
"sorting points",
"iterating points",
"calculating sidedness",
)
util.stacked_bar(ax=ax,
data=[[result["times"][step] * 1000] for step in steps],
series_labels=steps,
category_labels=["graham scan"],
value_format="{:.1f}")
def plot_gift(result, ax):
steps = (
"other",
"calculating angle",
"calculating vector",
)
util.stacked_bar(ax=ax,
data=[[result["times"][step] * 1000] for step in steps],
series_labels=steps,
category_labels=["gift wrapper"],
value_format="{:.1f}")
def plot_quick(result, ax):
steps = (
"other",
"partitioning set",
"finding farthest point from line",
)
util.stacked_bar(ax=ax,
data=[[result["times"][step] * 1000] for step in steps],
series_labels=steps,
category_labels=["quickhull"],
value_format="{:.1f}")
def do_profile():
num_points = 60_000
results = do_one_profile(num_points)
print("================== RESULTS ==================")
print(json.dumps(results))
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, sharex=False, sharey=True, gridspec_kw={"width_ratios": (1, 1, 4)})
fig.add_subplot(111, frameon=False)
plt.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')
plt.ylabel("time (ms)")
plt.subplots_adjust(wspace=0)
plot_graham(results["graham_scan"], ax1)
#plot_gift(results["gift_wrapper"], ax2)
plot_quick(results["quick_hull"], ax2)
plot_mbc({alg: data
for alg, data in results.items()
if alg.startswith("mbc")},
ax3)
plt.show()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -134,9 +134,9 @@ class Side(Enum):
BELOW = auto() BELOW = auto()
def stacked_bar(data, series_labels, category_labels=None, def stacked_bar(ax, data, series_labels, category_labels=None,
show_values=False, value_format="{}", y_label=None, show_values=True, value_format="{}", y_label=None,
grid=True, reverse=False): grid=False, reverse=False):
""" """
Plots a stacked bar chart with the data and labels provided (https://stackoverflow.com/a/50205834). Plots a stacked bar chart with the data and labels provided (https://stackoverflow.com/a/50205834).
@ -171,28 +171,32 @@ def stacked_bar(data, series_labels, category_labels=None,
category_labels = reversed(category_labels) category_labels = reversed(category_labels)
for i, row_data in enumerate(data): for i, row_data in enumerate(data):
axes.append(plt.bar(ind, row_data, bottom=cum_size, axes.append(ax.bar(ind, row_data, bottom=cum_size,
label=series_labels[i])) label=series_labels[i]))
cum_size += row_data cum_size += row_data
if category_labels: if category_labels:
plt.sca(ax)
plt.xticks(ind, category_labels) plt.xticks(ind, category_labels)
if y_label: if y_label:
plt.ylabel(y_label) plt.ylabel(y_label)
plt.legend() ax.legend()
# Reverse legend (https://stackoverflow.com/a/34576778)
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles[::-1], labels[::-1])
if grid: if grid:
plt.grid() ax.grid()
if show_values: if show_values:
for axis in axes: for axis in axes:
for bar in axis: for bar in axis:
w, h = bar.get_width(), bar.get_height() w, h = bar.get_width(), bar.get_height()
if h != 0: if h != 0:
plt.text(bar.get_x() + w/2, bar.get_y() + h/2, ax.text(bar.get_x() + w/2, bar.get_y() + h/2,
value_format.format(h), ha="center", value_format.format(h), ha="center",
va="center") va="center")
plt.show() #plt.show()