Evalml: Batas Waktu Uji Unit (Ketidakstabilan Dask)

Dibuat pada 9 Jun 2021  ·  11Komentar  ·  Sumber: alteryx/evalml

Saat ini kami melihat pengujian unit mencapai batas Tindakan GH 6 jam. Ini tidak baik untuk alasan yang jelas.

3,8 inti deps 6 jam batas waktu (sedang berlangsung)
build_conda_pkg, 3,8 deps inti, 3,7 deps non-inti batas waktu 6 jam (sedang berlangsung)
3,7 non-inti deps 6 jam timeout
3,8 non-inti deps 6 jam batas waktu
3,7 deps non-inti 1,5 jam
build_conda_pkg
3.7 deps non-inti
3.8

blocker bug testing

Komentar yang paling membantu

Saya sekarang melihat stacktrace berikut di 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

Ini tampaknya menjadi masalah yang diketahui di dask https://github.com/dask/distributed/issues/4612

Semua 11 komentar

Hanya menambahkan beberapa data dari 3.8 core deps ini menjalankan serangkaian pemeriksaan. Menambahkan log dari proses itu.

github_unittests.txt

Saya pikir satu hal yang saya perhatikan adalah bahwa mereka semua berhenti di sekitar tanda selesai 91-93%. Saya ragu ada nilai untuk mencari tahu tes mana itu, tapi itu mungkin rute yang harus ditempuh.

Ini satu lagi untuk 3,9 deps non-inti.

github_unittests_2.txt

Terima kasih telah mengajukan @chukarsten

Untungnya kami dapat mengesampingkan conda sebagai penyebabnya, karena ini terjadi pada unit test build normal kami dan bukan hanya untuk build_conda_pkg

Apakah ada info lain yang harus kami kumpulkan yang dapat membantu kami mengetahui hal ini? Beberapa ide di bawah ini

  • Seberapa andal kita dapat mengulangi batas waktu? Apakah itu terjadi 50% dari waktu kita menjalankan pekerjaan unit test, lebih banyak, lebih sedikit?
  • Tes atau tes mana yang tidak diselesaikan dengan benar? Jika kita bisa mendapatkan pytest untuk mencatat awal dan akhir setiap tes, kita bisa melihat log dan menyimpulkan tes mana yang belum berakhir saat hang terjadi. Ini tampak berpotensi berguna.
  • Apakah kita masih melihat batas waktu ini jika kita menjalankan tes tanpa paralelisasi pytest?
  • Ini hanya firasat, tetapi apa yang terjadi jika kita menonaktifkan tes mesin dask? Saya tahu kami telah melihat beberapa serpihan dengan yang baru-baru ini #2341
  • Seperti apa penggunaan CPU dan memori saat pengujian berjalan?

( @freddyaboulton saya menambahkan Anda di sini karena ini terhubung ke #2298 dan #1815)

Mengubah Makefile untuk melakukan verbose logging dengan pytest, kita mendapatkan log berikut:
. Ini menunjukkan tes yang terakhir dieksekusi adalah "evalml/tuners/random_search_tuner.py::evalml.tuners.random_search_tuner.RandomSearchTuner"

Saya pikir @freddyaboulton pasti ada sesuatu di sini dan kami menunjuk dengan tegas ke Dask. Membuat PR ini untuk memisahkan tes unit dask. Saya pikir kami memiliki opsi untuk tidak mencegah penggabungan jika gagal. PR ini gagal pada test_automl_immediate_quit, yang masih dalam rangkaian tes dask.

Melihat ke akar penyebab kegagalan tes unit dask membingungkan. Log menghasilkan banyak ini:

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'

Mengapa ini terjadi? Sepertinya di mana pun data yang ditindaklanjuti kehilangan referensi ke data itu. Selain itu 'pekerja: []' menunjukkan bahwa mungkin proses pengasuh membunuh para pekerja. Saya curiga ada sesuatu yang terjadi dengan bagaimana data tersebar tetapi saya juga curiga dengan apa yang terjadi di balik selimut dengan keempat pekerjaan ini berjalan bersama dalam paralel/seri semu.

Masalah terdistribusi dask ini menyarankan untuk menonaktifkan penskalaan adaptif untuk cluster. Sayangnya kami tidak menggunakan cluster adaptif, hanya cluster statis lokal biasa, jadi bukan itu masalahnya. Masalah ini menunjukkan hamburan data sebagai penyebab potensial masalah, di mana pekerja ditinggalkan, tetapi kami tidak mendapatkan kesalahan koneksi yang sama.

Setelah mencoba #2376 untuk memisahkan tugas dask dan menyetel broadcast=False untuk klien DaskEngine, secara default, saya mengalami kegagalan uji coba dengan test_automl_immediate_quit. Didokumentasikan di sini .

Saya sekarang melihat stacktrace berikut di 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

Ini tampaknya menjadi masalah yang diketahui di dask https://github.com/dask/distributed/issues/4612

Menghapus posting lama saya tetapi ini yang merah: https://github.com/alteryx/evalml/actions/runs/939673304 , tampaknya merupakan jejak tumpukan yang sama @freddyaboulton yang diposting di atas.

Saya percaya masalah ini tidak lagi memblokir per [PR ini] untuk memisahkan pekerjaan dask (https://github.com/alteryx/evalml/pull/2376), PR ini untuk memperbaiki pekerjaan dask untuk mengurangi serpihan, dan PR ini untuk membuat pekerjaan dask terpisah tidak memblokir untuk digabungkan ke utama dan PR ini untuk menambahkan batas waktu untuk mencegah tes dasbor patologis memakan waktu 6 jam hingga akhirnya dibatalkan oleh Tindakan GH.

Akan memindahkan ini ke ditutup karena batas waktu terkait dask sekarang tidak lagi menjadi masalah dan seharusnya tidak terjadi di masa mendatang. Namun, penyebab yang mendasarinya masih belum diketahui.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat