Skip to content

Make backend deletion robust after fit #1155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 6, 2021
27 changes: 19 additions & 8 deletions autosklearn/automl.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
from autosklearn.evaluation.abstract_evaluator import _fit_and_suppress_warnings
from autosklearn.evaluation.train_evaluator import TrainEvaluator, _fit_with_budget
from autosklearn.metrics import calculate_metric
from autosklearn.util.backend import Backend
from autosklearn.util.backend import Backend, create
from autosklearn.util.stopwatch import StopWatch
from autosklearn.util.logging_ import (
setup_logger,
Expand Down Expand Up @@ -113,9 +113,10 @@ def send_warnings_to_log(
class AutoML(BaseEstimator):

def __init__(self,
backend: Backend,
time_left_for_this_task,
per_run_time_limit,
temporary_directory: Optional[str] = None,
delete_tmp_folder_after_terminate: bool = True,
initial_configurations_via_metalearning=25,
ensemble_size=1,
ensemble_nbest=1,
Expand All @@ -141,7 +142,9 @@ def __init__(self,
):
super(AutoML, self).__init__()
self.configuration_space = None
self._backend = backend
self._backend: Optional[Backend] = None
self._temporary_directory = temporary_directory
self._delete_tmp_folder_after_terminate = delete_tmp_folder_after_terminate
# self._tmp_dir = tmp_dir
self._time_for_task = time_left_for_this_task
self._per_run_time_limit = per_run_time_limit
Expand Down Expand Up @@ -228,6 +231,12 @@ def __init__(self,
# saved to disk
self.num_run = 0

def _create_backend(self) -> Backend:
return create(
temporary_directory=self._temporary_directory,
delete_tmp_folder_after_terminate=self._delete_tmp_folder_after_terminate,
)

def _create_dask_client(self):
self._is_dask_client_internally_created = True
self._dask_client = dask.distributed.Client(
Expand Down Expand Up @@ -436,6 +445,9 @@ def fit(
if dataset_name is None:
dataset_name = str(uuid.uuid1(clock_seq=os.getpid()))

# Create the backend
self._backend = self._create_backend()

# By default try to use the TCP logging port or get a new port
self._logger_port = logging.handlers.DEFAULT_TCP_LOGGING_PORT
self._logger = self._get_logger(dataset_name)
Expand Down Expand Up @@ -805,6 +817,10 @@ def _fit_cleanup(self):
# Clean up the logger
self._logger.info("Starting to clean up the logger")
self._clean_logger()

# Clean up the backend
if self._delete_tmp_folder_after_terminate:
self._backend.context.delete_directories(force=False)
return

def _check_resampling_strategy(
Expand Down Expand Up @@ -1594,11 +1610,6 @@ def __del__(self):

self._close_dask_client()

# When a multiprocessing work is done, the
# objects are deleted. We don't want to delete run areas
# until the estimator is deleted
self._backend.context.delete_directories(force=False)


class AutoMLClassifier(AutoML):
def __init__(self, *args, **kwargs):
Expand Down
7 changes: 1 addition & 6 deletions autosklearn/estimators.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from autosklearn.pipeline.base import BasePipeline
from autosklearn.automl import AutoMLClassifier, AutoMLRegressor, AutoML
from autosklearn.metrics import Scorer
from autosklearn.util.backend import create


class AutoSklearnEstimator(BaseEstimator):
Expand Down Expand Up @@ -284,13 +283,9 @@ def __getstate__(self):

def build_automl(self):

backend = create(
automl = self._get_automl_class()(
temporary_directory=self.tmp_folder,
delete_tmp_folder_after_terminate=self.delete_tmp_folder_after_terminate,
)

automl = self._get_automl_class()(
backend=backend,
time_left_for_this_task=self.time_left_for_this_task,
per_run_time_limit=self.per_run_time_limit,
initial_configurations_via_metalearning=self.initial_configurations_via_metalearning,
Expand Down
1 change: 1 addition & 0 deletions examples/60_search/example_parallel_manual_spawning_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def cli_start_worker(scheduler_file_name):
X_train, X_test, y_train, y_test = \
sklearn.model_selection.train_test_split(X, y, random_state=1)
automl = AutoSklearnClassifier(
delete_tmp_folder_after_terminate=False,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, what's the reason for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a very good question. I have made it so, that backend is created on a need basis and destroyed after it is no longer needed. We cannot relay on the del method.

If you look a couple of lines below, we do fit_ensemble. If we do not preserve the backend after fit, the backend directory will be removed.

time_left_for_this_task=30,
per_run_time_limit=10,
memory_limit=1024,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ async def do_work():
# 3. Start the client
with dask.distributed.Client(address=cluster.scheduler_address) as client:
automl = AutoSklearnClassifier(
delete_tmp_folder_after_terminate=False,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here?

time_left_for_this_task=30,
per_run_time_limit=10,
memory_limit=1024,
Expand Down
Loading