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)
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:]:
while len(UH) > 1 and (sidedness(UH[-2], UH[-1], s) != Side.ABOVE):
del UH[-1]
UH.append(s)
with Profiler("reversing list"):
reversed_list = list(reversed(sorted_points))
reversed_list.append(UH[0])
reversed_list = list(reversed(sorted_points))
reversed_list.append(UH[0])
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:]:
while len(LH) > 1 and (sidedness(LH[-2], LH[-1], s) != Side.ABOVE):
del LH[-1]

View File

@ -10,6 +10,9 @@ from profile import Profiler
from quick_hull import quick_hull
import os.path
import matplotlib.pyplot as plt
#random.seed(1337_420)
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)}
tests = [
#("graham_scan", graham_scan),
("graham_scan", graham_scan),
#("gift_wrapper", rapper),
#("quick_hull", quick_hull),
("quick_hull", quick_hull),
("mbc", mbc),
("mbc2", mbc2),
("mbc_no_shuffle", mbc_no_shuffle),
@ -135,38 +138,94 @@ def do_one_profile(num_points):
return results
def do_profile():
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))
def plot_mbc(results, ax):
algorithms = list(results.keys())
steps = (
"other",
"finding median",
"partitioning set",
"flipping constraints",
"solving 2D",
"solving LP",
"finding bridge points",
"pruning between line points",
"shuffling constraints",
"extra pruning step",
)
data = [[result["times"].get(step, 0) * 1000 for result in results.values()]
for step in steps]
util.stacked_bar(data=data,
util.stacked_bar(ax=ax,
data=[[result["times"].get(step, 0) * 1000 for result in results.values()] for step in steps],
series_labels=steps,
category_labels=algorithms,
show_values=True,
value_format="{:.1f}",
y_label="time (ms)",
grid=False,
reverse=False)
value_format="{:.1f}")
def plot_graham(result, ax):
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__':

View File

@ -134,9 +134,9 @@ class Side(Enum):
BELOW = auto()
def stacked_bar(data, series_labels, category_labels=None,
show_values=False, value_format="{}", y_label=None,
grid=True, reverse=False):
def stacked_bar(ax, data, series_labels, category_labels=None,
show_values=True, value_format="{}", y_label=None,
grid=False, reverse=False):
"""
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)
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]))
cum_size += row_data
if category_labels:
plt.sca(ax)
plt.xticks(ind, category_labels)
if 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:
plt.grid()
ax.grid()
if show_values:
for axis in axes:
for bar in axis:
w, h = bar.get_width(), bar.get_height()
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",
va="center")
plt.show()
#plt.show()