Evalml: Einheitentest-Timeouts (Dask-Instabilität)

Erstellt am 9. Juni 2021  ·  11Kommentare  ·  Quelle: alteryx/evalml

Wir sehen derzeit, dass Unit-Tests das Limit für GH-Aktionen von 6 Stunden erreichen. Das ist aus offensichtlichen Gründen nicht gut.

3.8 Core Deps 6 Stunden Timeout (in Bearbeitung)
build_conda_pkg, 3,8 Kernabt., 3,7 Nicht-Kernabt. 6 Std. Timeout (in Bearbeitung)
3.7 Nicht-Kern-Abhängigkeiten 6 Std. Timeout
3.8 Nicht-Kern-Abhängigkeiten 6 Std. Timeout
3,7 Nicht-Kern-Abhängigkeiten 1,5 Std.
build_conda_pkg
3.7 Nicht-Kern-Deps
3.8

blocker bug testing

Hilfreichster Kommentar

Ich sehe jetzt den folgenden Stacktrace in build_conda_pkg

[gw3] linux -- Python 3.7.10 $PREFIX/bin/python

X_y_binary_cls = (          0         1         2   ...        17        18        19
0  -0.039268  0.131912 -0.211206  ...  1.976989  ...ns], 0     0
1     0
2     1
3     1
4     1
     ..
95    1
96    1
97    1
98    1
99    0
Length: 100, dtype: int64)
cluster = LocalCluster(15c4b3ad, 'tcp://127.0.0.1:45201', workers=0, threads=0, memory=0 B)

    def test_submit_training_jobs_multiple(X_y_binary_cls, cluster):
        """Test that training multiple pipelines using the parallel engine produces the
        same results as the sequential engine."""
        X, y = X_y_binary_cls
        with Client(cluster) as client:
            pipelines = [
                BinaryClassificationPipeline(
                    component_graph=["Logistic Regression Classifier"],
                    parameters={"Logistic Regression Classifier": {"n_jobs": 1}},
                ),
                BinaryClassificationPipeline(component_graph=["Baseline Classifier"]),
                BinaryClassificationPipeline(component_graph=["SVM Classifier"]),
            ]

            def fit_pipelines(pipelines, engine):
                futures = []
                for pipeline in pipelines:
                    futures.append(
                        engine.submit_training_job(
                            X=X, y=y, automl_config=automl_data, pipeline=pipeline
                        )
                    )
                results = [f.get_result() for f in futures]
                return results

            # Verify all pipelines are trained and fitted.
            seq_pipelines = fit_pipelines(pipelines, SequentialEngine())
            for pipeline in seq_pipelines:
                assert pipeline._is_fitted

            # Verify all pipelines are trained and fitted.
>           par_pipelines = fit_pipelines(pipelines, DaskEngine(client=client))

evalml/tests/automl_tests/dask_tests/test_dask_engine.py:103: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
evalml/tests/automl_tests/dask_tests/test_dask_engine.py:94: in fit_pipelines
    results = [f.get_result() for f in futures]
evalml/tests/automl_tests/dask_tests/test_dask_engine.py:94: in <listcomp>
    results = [f.get_result() for f in futures]
evalml/automl/engine/dask_engine.py:30: in get_result
    return self.work.result()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Future: cancelled, key: train_pipeline-4bd4a99325cd3cc91144f86b64d6503c>
timeout = None

    def result(self, timeout=None):
        """Wait until computation completes, gather result to local process.

        If *timeout* seconds are elapsed before returning, a
        ``dask.distributed.TimeoutError`` is raised.
        """
        if self.client.asynchronous:
            return self.client.sync(self._result, callback_timeout=timeout)

        # shorten error traceback
        result = self.client.sync(self._result, callback_timeout=timeout, raiseit=False)
        if self.status == "error":
            typ, exc, tb = result
            raise exc.with_traceback(tb)
        elif self.status == "cancelled":
>           raise result
E           concurrent.futures._base.CancelledError: train_pipeline-4bd4a99325cd3cc91144f86b64d6503c

Dies scheint ein bekanntes Problem in Dask zu sein https://github.com/dask/distributed/issues/4612

Alle 11 Kommentare

Fügen Sie einfach einige Daten aus

github_unittests.txt

Ich denke, eine Sache, die mir aufgefallen ist, ist, dass sie alle um die 91-93 %-Marke herum pausieren. Ich bezweifle, dass es einen Wert hat, herauszufinden, welche Tests das sind, aber das könnte ein Weg sein, den man verfolgen sollte.

Hier ist ein weiteres für 3.9 Nicht-Kern-Deps.

github_unittests_2.txt

Danke für die Einreichung @chukarsten

Glücklicherweise können wir Conda als Ursache ausschließen, da dies für unsere normalen Unit-Test-Builds und nicht nur für build_conda_pkg Fall ist

Gibt es noch andere Informationen, die wir sammeln sollten, die uns helfen könnten, dies herauszufinden? Ein paar Ideen unten

  • Wie zuverlässig können wir den Timeout reproduzieren? Geschieht es in 50 % der Zeit, in der wir Unit-Test-Jobs ausführen, mehr, weniger?
  • Welcher Test oder welche Tests werden nicht richtig abgeschlossen? Wenn wir pytest dazu bringen können, den Start und das Ende jedes Tests zu protokollieren, können wir uns die Protokolle ansehen und daraus ableiten, welcher Test noch nicht beendet ist, wenn das Hängen auftritt. Das sah potenziell nützlich aus.
  • Sehen wir diese Zeitüberschreitungen immer noch, wenn wir Tests ohne pytest-Parallelisierung ausführen?
  • Dies ist nur eine Vermutung, aber was passiert, wenn wir die Dask-Engine-Tests deaktivieren? Ich weiß, wir haben vor kurzem ein paar Flocken mit denen gesehen # 2341
  • Wie sieht die CPU- und Speicherauslastung während der Tests aus?

( @freddyaboulton Ich habe dich hier hinzugefügt, da dies mit #2298 und #1815) verbunden ist.

Wenn wir das Makefile ändern, um ausführliches Logging mit pytest durchzuführen, erhalten wir das folgende Protokoll
. Dies zeigt, dass der zuletzt ausgeführte Test "evalml/tuners/random_search_tuner.py::evalml.tuners.random_search_tuner.RandomSearchTuner" ist.

Nachdem ich die Zeitüberschreitung hinzugefügt habe, habe ich die gleiche Zeitüberschreitung bei test_dask_sends_woodwork_schema mindestens dreimal gesehen:

  1. https://github.com/alteryx/evalml/pull/2374/checks?check_run_id=2804775673
  2. https://github.com/alteryx/evalml/pull/2374/checks?check_run_id=2804202831#step :9:92
  3. https://github.com/alteryx/evalml/runs/2804668851?check_suite_focus=true

Ich denke, @freddyaboulton steht hier sicherlich auf etwas und wir zeigen fest auf Dask. Habe diesen PR gemacht , um die Dask-Unit-Tests zu trennen. Ich denke, wir haben die Möglichkeit, die Zusammenführung nicht zu verhindern, wenn sie fehlschlagen. Diese PR ist bei test_automl_immediate_quit fehlgeschlagen, das sich immer noch im Array der Dask-Tests befindet.

Es ist rätselhaft, die Ursache für die Fehler beim Test der Dask-Einheit zu untersuchen. Die Protokolle erzeugen eine Menge davon:

distributed.worker - WARNING - Could not find data: {'Series-32a3ef2ca4739b46a6acc2ac58638b32': ['tcp://127.0.0.1:45587']} on workers: [] (who_has: {'Series-32a3ef2ca4739b46a6acc2ac58638b32': ['tcp://127.0.0.1:45587']})
distributed.scheduler - WARNING - Communication failed during replication: {'status': 'missing-data', 'keys'

Warum passiert das? Nun, es scheint, dass überall dort, wo die Daten verarbeitet werden, der Bezug zu diesen Daten verloren geht. Außerdem deutet das 'workers: []' darauf hin, dass der Nanny-Prozess vielleicht die Arbeiter tötet. Ich vermute, dass etwas mit der Streuung der Daten vor sich geht, aber ich bin auch misstrauisch, was unter der Decke passiert, wenn diese vier Jobs pseudoparallel/seriell zusammenlaufen.

Dieses Problem mit der Verteilung von Dask schlägt vor, die adaptive Skalierung für den Cluster zu deaktivieren. Leider verwenden wir keine adaptiven Cluster, sondern nur normale lokale, statische Cluster, das ist also nicht das Problem. Dieses Problem weist auf die Streuung der Daten als mögliche Ursache des Problems hin, bei der Mitarbeiter verlassen werden, aber wir nicht die gleichen Verbindungsfehler erhalten.

Nachdem ich #2376 versucht habe, die Dask-Jobs zu trennen und broadcast=False für den DaskEngine-Client festzulegen, habe ich standardmäßig einen flockigen Testfehler mit test_automl_immediate_quit. Dokumentierte hier .

Ich sehe jetzt den folgenden Stacktrace in build_conda_pkg

[gw3] linux -- Python 3.7.10 $PREFIX/bin/python

X_y_binary_cls = (          0         1         2   ...        17        18        19
0  -0.039268  0.131912 -0.211206  ...  1.976989  ...ns], 0     0
1     0
2     1
3     1
4     1
     ..
95    1
96    1
97    1
98    1
99    0
Length: 100, dtype: int64)
cluster = LocalCluster(15c4b3ad, 'tcp://127.0.0.1:45201', workers=0, threads=0, memory=0 B)

    def test_submit_training_jobs_multiple(X_y_binary_cls, cluster):
        """Test that training multiple pipelines using the parallel engine produces the
        same results as the sequential engine."""
        X, y = X_y_binary_cls
        with Client(cluster) as client:
            pipelines = [
                BinaryClassificationPipeline(
                    component_graph=["Logistic Regression Classifier"],
                    parameters={"Logistic Regression Classifier": {"n_jobs": 1}},
                ),
                BinaryClassificationPipeline(component_graph=["Baseline Classifier"]),
                BinaryClassificationPipeline(component_graph=["SVM Classifier"]),
            ]

            def fit_pipelines(pipelines, engine):
                futures = []
                for pipeline in pipelines:
                    futures.append(
                        engine.submit_training_job(
                            X=X, y=y, automl_config=automl_data, pipeline=pipeline
                        )
                    )
                results = [f.get_result() for f in futures]
                return results

            # Verify all pipelines are trained and fitted.
            seq_pipelines = fit_pipelines(pipelines, SequentialEngine())
            for pipeline in seq_pipelines:
                assert pipeline._is_fitted

            # Verify all pipelines are trained and fitted.
>           par_pipelines = fit_pipelines(pipelines, DaskEngine(client=client))

evalml/tests/automl_tests/dask_tests/test_dask_engine.py:103: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
evalml/tests/automl_tests/dask_tests/test_dask_engine.py:94: in fit_pipelines
    results = [f.get_result() for f in futures]
evalml/tests/automl_tests/dask_tests/test_dask_engine.py:94: in <listcomp>
    results = [f.get_result() for f in futures]
evalml/automl/engine/dask_engine.py:30: in get_result
    return self.work.result()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <Future: cancelled, key: train_pipeline-4bd4a99325cd3cc91144f86b64d6503c>
timeout = None

    def result(self, timeout=None):
        """Wait until computation completes, gather result to local process.

        If *timeout* seconds are elapsed before returning, a
        ``dask.distributed.TimeoutError`` is raised.
        """
        if self.client.asynchronous:
            return self.client.sync(self._result, callback_timeout=timeout)

        # shorten error traceback
        result = self.client.sync(self._result, callback_timeout=timeout, raiseit=False)
        if self.status == "error":
            typ, exc, tb = result
            raise exc.with_traceback(tb)
        elif self.status == "cancelled":
>           raise result
E           concurrent.futures._base.CancelledError: train_pipeline-4bd4a99325cd3cc91144f86b64d6503c

Dies scheint ein bekanntes Problem in Dask zu sein https://github.com/dask/distributed/issues/4612

Meinen alten Beitrag gelöscht, aber hier ist ein roter: https://github.com/alteryx/evalml/actions/runs/939673304 , scheint der gleiche Stack-Trace @freddyaboulton zu sein, der

Ich glaube, dieses Problem blockiert nicht mehr pro [dieser PR], um die Dask-Jobs (https://github.com/alteryx/evalml/pull/2376) zu trennen, diese PR, um die Dask-Jobs umzugestalten, um Flocken zu reduzieren, und dieser PR , damit die separaten Dask-Jobs nicht für die Zusammenführung mit dem Main blockiert werden, und dieser PR , um eine Zeitüberschreitung hinzuzufügen, um zu verhindern, dass pathologische Dask-Tests 6 Stunden brauchen, um schließlich von GH Actions abgebrochen zu werden.

Ich werde dies auf geschlossen verschieben, da die Dask-bezogenen Timeouts jetzt kein Problem mehr sind und auf absehbare Zeit nicht mehr sein sollten. Die zugrunde liegende Ursache ist jedoch noch unbekannt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen