Added a first version of the database's common-best default calculation

This commit is contained in:
Cedric Nugteren 2016-08-07 16:25:38 +02:00
parent 35623cd98d
commit 3f5401d4c8
2 changed files with 64 additions and 9 deletions

View file

@ -98,7 +98,8 @@ def main(argv):
database_best_results = bests.get_best_results(database)
# Determines the defaults for other vendors and per vendor
database_defaults = defaults.calculate_defaults(database_best_results)
print("[database] Calculating the default values...")
database_defaults = defaults.calculate_defaults(database)
database_best_results = db.concatenate_database(database_best_results, database_defaults)
# Outputs the database as a C++ database

View file

@ -6,7 +6,9 @@
# Cedric Nugteren <www.cedricnugteren.nl>
import pandas as pd
import clblast
import bests
def set_default_device(database_entry):
@ -23,16 +25,18 @@ def set_default_time(database_entry):
return database_entry
def calculate_defaults(df):
"""# Sets defaults for devices of the same type/vendor based on the smallest values of all known entries. The average
might be better for performance but some parameters might not be supported on other devices."""
def calculate_defaults(database, calculate_common_best=True):
"""Sets defaults for devices of the same type/vendor. An option determines how to compute the defaults."""
database_defaults = pd.DataFrame()
# Defaults per combination of device vendors and device types (e.g. AMD GPU)
database_type_vendor = df.groupby(clblast.DEVICE_TYPE_ATTRIBUTES + clblast.KERNEL_ATTRIBUTES + ["kernel"] +
clblast.ARGUMENT_ATTRIBUTES)
database_type_vendor = database.groupby(clblast.DEVICE_TYPE_ATTRIBUTES + clblast.KERNEL_ATTRIBUTES + ["kernel"] +
clblast.ARGUMENT_ATTRIBUTES)
for group_name, database_group in database_type_vendor:
default_values = database_group.min(axis=0)
if calculate_common_best:
default_values = get_common_best(database_group, group_name)
else:
default_values = get_smallest_best(database_group)
default_values = set_default_device(default_values)
default_values = set_default_time(default_values)
database_defaults = database_defaults.append(default_values, ignore_index=True)
@ -45,9 +49,9 @@ def calculate_defaults(df):
print("[WARNING] Entries for a single kernel with multiple argument values: " + description)
# Defaults over all device types and vendors
groups = df.groupby(clblast.KERNEL_ATTRIBUTES + ["kernel"] + clblast.ARGUMENT_ATTRIBUTES)
groups = database.groupby(clblast.KERNEL_ATTRIBUTES + ["kernel"] + clblast.ARGUMENT_ATTRIBUTES)
for group_name, database_group in groups:
default_values = database_group.min(axis=0)
default_values = get_smallest_best(database_group)
default_values["device_vendor"] = clblast.VENDOR_DEFAULT
default_values["device_type"] = clblast.DEVICE_TYPE_DEFAULT
default_values = set_default_device(default_values)
@ -56,3 +60,53 @@ def calculate_defaults(df):
# Database with both types of defaults only
return database_defaults
def get_smallest_best(database):
"""Sets defaults based on the smallest values of all known entries. The average might be better for performance but
some parameters might not be supported on other devices."""
database_best_results = bests.get_best_results(database)
return database_best_results.min(axis=0)
def get_common_best(database, group_name):
"""Sets defaults based on the best values of entries supported by all devices. This might cause a problem in case
not every device was tuned with the same parameters."""
# TODO: Quite a bit slower than the above `get_smallest_best` method
# Counts the number of devices in this group
num_devices = len(database.groupby(clblast.DEVICE_ATTRIBUTES))
# Removes columns without any values
database = database.dropna(axis=1, how='all')
# Retrieves the parameter names for this kernel
all_column_names = list(database.columns.values)
parameter_column_names = [c for c in all_column_names if "parameters." in c]
# Removes entries which are not available for all devices
database_common = pd.DataFrame()
database_by_parameters = database.groupby(parameter_column_names)
for parameter_values, database_parameters in database_by_parameters:
num_entries = database_parameters.shape[0]
if num_entries == num_devices:
database_common = database_common.append(database_parameters)
# Fall back to another method in case there are no shared entries at all across devices
if database_common.shape[0] == 0:
# print("Skipping: " + str(group_name) + " with devices: " + str(num_devices) + " " + str(database.shape[0]))
return get_smallest_best(database)
# Computes the sum of the execution times over the different devices
database_common['time'] = database_common.groupby(parameter_column_names)['time'].transform(sum)
# Retrieves the entries with the best execution time
best_time = database_common["time"].min()
database_bests = database_common[database_common["time"] == best_time]
# Retrieves one example only (the parameters are the same anyway)
database_bests = database_bests.drop_duplicates(["time"])
# print(str(group_name) + " with num devices: " + str(num_devices) + " " + str(database_bests.shape))
assert database_bests.shape[0] == 1
return database_bests