CPU lebih cepat dari GPU yang menggunakan xgb dan XGBclassifier

Aug 17 2020

Saya mohon maaf sebelumnya karena saya seorang pemula. Saya mencoba tes GPU vs CPU dengan XGBoost menggunakan xgb dan XGBclassifier. Hasilnya adalah sebagai berikut:

   passed time with xgb (gpu): 0.390s
   passed time with XGBClassifier (gpu): 0.465s
   passed time with xgb (cpu): 0.412s
   passed time with XGBClassifier (cpu): 0.421s

Saya bertanya-tanya mengapa CPU tampaknya berkinerja setara jika tidak lebih baik dari GPU. Ini adalah pengaturan saya:

  • Python 3.6.1
  • OS: Windows 10 64bit
  • GPU: NVIDIA RTX 2070 Super 8gb vram (driver diperbarui ke versi terbaru)
  • CUDA 10.1 diinstal
  • CPU i7 10700 2.9Ghz
  • Berjalan di Notebook Jupyter
  • Memasang nightly build dari xgboost 1.2.0 melalui pip

** juga mencoba menggunakan versi xgboost yang dipasang dari roda biner yang dibuat sebelumnya menggunakan pip: masalah yang sama

Ini kode tes yang saya gunakan (diambil dari sini ):

param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
              'colsample_bytree':0.8, 'eta':0.5, 'min_child_weight':1,
              'tree_method':'gpu_hist'
              }

num_round = 100

dtrain = xgb.DMatrix(X_train2, y_train)
tic = time.time()
model = xgb.train(param, dtrain, num_round)
print('passed time with xgb (gpu): %.3fs'%(time.time()-tic))

xgb_param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
         'colsample_bytree':0.8, 'learning_rate':0.5, 'min_child_weight':1,
         'tree_method':'gpu_hist'}
model = xgb.XGBClassifier(**xgb_param)
tic = time.time()
model.fit(X_train2, y_train)
print('passed time with XGBClassifier (gpu): %.3fs'%(time.time()-tic))

param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
         'colsample_bytree':0.8, 'eta':0.5, 'min_child_weight':1,
         'tree_method':'hist'}
num_round = 100

dtrain = xgb.DMatrix(X_train2, y_train)
tic = time.time()
model = xgb.train(param, dtrain, num_round)
print('passed time with xgb (cpu): %.3fs'%(time.time()-tic))

xgb_param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
         'colsample_bytree':0.8, 'learning_rate':0.5, 'min_child_weight':1,
         'tree_method':'hist'}
model = xgb.XGBClassifier(**xgb_param)
tic = time.time()
model.fit(X_train2, y_train)
print('passed time with XGBClassifier (cpu): %.3fs'%(time.time()-tic))

Saya telah mencoba menggabungkan pencarian grid Sklearn untuk melihat apakah saya akan mendapatkan kecepatan yang lebih cepat pada GPU tetapi akhirnya menjadi jauh lebih lambat daripada CPU:

passed time with XGBClassifier (gpu): 2457.510s
Best parameter (CV score=0.490):
{'xgbclass__alpha': 100, 'xgbclass__eta': 0.01, 'xgbclass__gamma': 0.2, 'xgbclass__max_depth': 5, 'xgbclass__n_estimators': 100}


passed time with XGBClassifier (cpu): 383.662s
Best parameter (CV score=0.487):
{'xgbclass__alpha': 100, 'xgbclass__eta': 0.1, 'xgbclass__gamma': 0.2, 'xgbclass__max_depth': 2, 'xgbclass__n_estimators': 20}

Saya menggunakan kumpulan data dengan 75 ribu observasi. Adakah ide mengapa saya tidak mendapatkan speedup dari menggunakan GPU? Apakah kumpulan data terlalu kecil untuk mendapatkan keuntungan dari penggunaan GPU?

Bantuan apa pun akan sangat dihargai. Terima kasih banyak!

Jawaban

6 wundermahn Jan 11 2021 at 19:47

Pertanyaan menarik. Seperti yang Anda catat, ada beberapa contoh ini yang telah dicatat di Github dan resminya xgboost site:

  • https://github.com/dmlc/xgboost/issues/2819
  • https://discuss.xgboost.ai/t/no-gpu-usage-when-using-gpu-hist/532

Ada juga orang lain yang memposting pertanyaan serupa:

  • Tidak ada percepatan menggunakan XGBClassifier dengan dukungan GPU

Melihat dokumentasi resmixgboost , ada bagian ekstensif tentang dukungan GPU .

Ada beberapa hal yang perlu diperiksa. Dokumentasi mencatat bahwa:

Konstruksi pohon (pelatihan) dan prediksi dapat dipercepat dengan GPU berkemampuan CUDA.

1. Apakah GPU CUDA Anda diaktifkan?

Ya, benar .

2. Apakah Anda menggunakan parameter yang dapat dipengaruhi oleh penggunaan GPU?

Perlu diingat, hanya parameter tertentu yang mendapatkan keuntungan dari penggunaan GPU. Yaitu:

Ya, kamu. Sebagian besar ini termasuk dalam kumpulan hyperparameter Anda, yang merupakan hal yang baik.

{subsample, sampling_method, colsample_bytree, colsample_bylevel, max_bin, gamma, gpu_id, predictor, grow_policy, monotone_constraints, interaction_constraints, single_precision_histogram}

3. Apakah Anda mengonfigurasi parameter untuk menggunakan dukungan GPU?

Jika Anda melihat halaman Parameter XGBoost , Anda dapat menemukan area tambahan yang dapat membantu meningkatkan waktu Anda. Misalnya, updaterdapat diatur ke grow_gpu_hist, yang (catatan, ini diperdebatkan karena Anda telah tree_methodmengatur, tetapi untuk catatan):

grow_gpu_hist: Tumbuhkan pohon dengan GPU.

Di bagian bawah halaman parameter, ada parameter tambahan untuk gpu_histdiaktifkan, khususnya deterministic_histogram(catatan, ini diperdebatkan karena ini defaultnya True):

Buat histogram di GPU secara deterministik. Pembuatan histogram tidak deterministik karena aspek non-asosiatif penjumlahan floating point. Kami menerapkan rutinitas pra-pembulatan untuk mengurangi masalah, yang dapat menyebabkan akurasi yang sedikit lebih rendah. Setel ke false untuk menonaktifkannya.

4. Data

Saya menjalankan beberapa eksperimen menarik dengan beberapa data. Karena saya tidak memiliki akses ke data Anda, saya menggunakan sklearns make_classification, yang menghasilkan data dengan cara yang cukup kuat .

Saya membuat beberapa perubahan pada skrip Anda tetapi tidak ada perubahan: Saya mengubah hyperparameter pada contoh gpu vs cpu, saya menjalankan ini 100 kali dan mengambil hasil rata-rata, dll. Sepertinya tidak ada yang menonjol bagi saya. Saya ingat bahwa saya pernah menggunakan XGBoostkemampuan GPU vs CPU untuk mempercepat beberapa analitik, namun, saya mengerjakan kumpulan data yang jauh lebih besar.

Saya mengedit skrip Anda sedikit untuk menggunakan data ini, dan juga mulai mengubah jumlah samplesdan featuresdalam dataset (melalui n_samplesdan n_featuresparameter) untuk mengamati efek pada runtime. Tampaknya GPU akan meningkatkan waktu pelatihan secara signifikan untuk data berdimensi tinggi , tetapi data massal dengan banyak sampel tersebut tidak melihat peningkatan yang besar. Lihat skrip saya di bawah ini:

import xgboost as xgb, numpy, time
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split

xgb_gpu = []
xgbclassifier_gpu = []
xgb_cpu = []
xgbclassifier_cpu = []

n_samples = 75000
n_features = 500

for i in range(len(10)):
    n_samples += 10000
    n_features += 300
    # Make my own data since I do not have the data from the SO question
    X_train2, y_train = make_classification(n_samples=n_samples, n_features=n_features*0.9, n_informative=n_features*0.1,
                                            n_redundant=100, flip_y=0.10, random_state=8)

    # Keep script from OP intact
    param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
                'colsample_bytree':0.8, 'eta':0.5, 'min_child_weight':1,
                'tree_method':'gpu_hist', 'gpu_id': 0
                }
    num_round = 100

    dtrain = xgb.DMatrix(X_train2, y_train)
    tic = time.time()
    model = xgb.train(param, dtrain, num_round)
    print('passed time with xgb (gpu): %.3fs'%(time.time()-tic))
    xgb_gpu.append(time.time()-tic)

    xgb_param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
            'colsample_bytree':0.8, 'learning_rate':0.5, 'min_child_weight':1,
            'tree_method':'gpu_hist', 'gpu_id':0}
    model = xgb.XGBClassifier(**xgb_param)
    tic = time.time()
    model.fit(X_train2, y_train)
    print('passed time with XGBClassifier (gpu): %.3fs'%(time.time()-tic))
    xgbclassifier_gpu.append(time.time()-tic)

    param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
            'colsample_bytree':0.8, 'eta':0.5, 'min_child_weight':1,
            'tree_method':'hist'}
    num_round = 100

    dtrain = xgb.DMatrix(X_train2, y_train)
    tic = time.time()
    model = xgb.train(param, dtrain, num_round)
    print('passed time with xgb (cpu): %.3fs'%(time.time()-tic))
    xgb_cpu.append(time.time()-tic)
    xgb_param = {'max_depth':5, 'objective':'binary:logistic', 'subsample':0.8, 
            'colsample_bytree':0.8, 'learning_rate':0.5, 'min_child_weight':1,
            'tree_method':'hist'}
    model = xgb.XGBClassifier(**xgb_param)
    tic = time.time()
    model.fit(X_train2, y_train)
    print('passed time with XGBClassifier (cpu): %.3fs'%(time.time()-tic))
    xgbclassifier_cpu.append(time.time()-tic)

import pandas as pd
df = pd.DataFrame({'XGB GPU': xgb_gpu, 'XGBClassifier GPU': xgbclassifier_gpu, 'XGB CPU': xgb_cpu, 'XGBClassifier CPU': xgbclassifier_cpu})
#df.to_csv('both_results.csv')

Saya menjalankan perubahan ini setiap (sampel, fitur) secara terpisah, dan bersama-sama, pada kumpulan data yang sama. Lihat hasil di bawah ini:

| Interval |  XGB GPU | XGBClassifier GPU |  XGB CPU | XGBClassifier CPU |      Metric      |
|:--------:|:--------:|:-----------------:|:--------:|:-----------------:|:----------------:|
|     0    |  11.3801 |      12.00785     | 15.20124 |      15.48131     | Changed Features |
|     1    | 15.67674 |      16.85668     | 20.63819 |      22.12265     | Changed Features |
|     2    | 18.76029 |      20.39844     | 33.23108 |      32.29926     | Changed Features |
|     3    |  23.147  |      24.91953     | 47.65588 |      44.76052     | Changed Features |
|     4    | 27.42542 |      29.48186     | 50.76428 |      55.88155     | Changed Features |
|     5    | 30.78596 |      33.03594     |  71.4733 |      67.24275     | Changed Features |
|     6    | 35.03331 |      37.74951     | 77.68997 |      75.61216     | Changed Features |
|     7    | 39.13849 |      42.17049     | 82.95307 |      85.83364     | Changed Features |
|     8    | 42.55439 |      45.90751     | 92.33368 |      96.72809     | Changed Features |
|     9    | 46.89023 |      50.57919     | 105.8298 |      107.3893     | Changed Features |
|     0    | 7.013227 |      7.303488     | 6.998254 |      9.733574     |    No Changes    |
|     1    | 6.757523 |      7.302388     | 5.714839 |      6.805287     |    No Changes    |
|     2    | 6.753428 |      7.291906     | 5.899611 |      6.603533     |    No Changes    |
|     3    | 6.749848 |      7.293555     | 6.005773 |      6.486256     |    No Changes    |
|     4    | 6.755352 |      7.297607     | 5.982163 |      8.280619     |    No Changes    |
|     5    | 6.756498 |      7.335412     | 6.321188 |      7.900422     |    No Changes    |
|     6    | 6.792402 |      7.332112     |  6.17904 |      6.443676     |    No Changes    |
|     7    | 6.786584 |      7.311666     | 7.093638 |      7.811417     |    No Changes    |
|     8    |  6.7851  |      7.30604      | 5.574762 |      6.045969     |    No Changes    |
|     9    | 6.789152 |      7.309363     | 5.751018 |      6.213471     |    No Changes    |
|     0    | 7.696765 |      8.03615      | 6.175457 |      6.764809     |  Changed Samples |
|     1    | 7.914885 |      8.646722     | 6.997217 |      7.598789     |  Changed Samples |
|     2    | 8.489555 |       9.2526      | 6.899783 |      7.202334     |  Changed Samples |
|     3    | 9.197605 |      10.02934     | 7.511708 |      7.724675     |  Changed Samples |
|     4    |  9.73642 |      10.64056     | 7.918493 |      8.982463     |  Changed Samples |
|     5    | 10.34522 |      11.31103     | 8.524865 |      9.403711     |  Changed Samples |
|     6    | 10.94025 |      11.98357     | 8.697257 |      9.49277      |  Changed Samples |
|     7    | 11.80717 |      12.93195     | 8.734307 |      10.79595     |  Changed Samples |
|     8    | 12.18282 |      13.38646     | 9.175231 |      10.33532     |  Changed Samples |
|     9    | 13.05499 |      14.33106     | 11.04398 |      10.50722     |  Changed Samples |
|     0    | 12.43683 |      13.19787     | 12.80741 |      13.86206     |   Changed Both   |
|     1    | 18.59139 |      20.01569     | 25.61141 |      35.37391     |   Changed Both   |
|     2    | 24.37475 |      26.44214     | 40.86238 |      42.79259     |   Changed Both   |
|     3    | 31.96762 |      34.75215     |  68.869  |      59.97797     |   Changed Both   |
|     4    | 41.26578 |      44.70537     | 83.84672 |      94.62811     |   Changed Both   |
|     5    | 49.82583 |      54.06252     |  109.197 |      108.0314     |   Changed Both   |
|     6    | 59.36528 |      64.60577     | 131.1234 |      140.6352     |   Changed Both   |
|     7    | 71.44678 |      77.71752     | 156.1914 |      161.4897     |   Changed Both   |
|     8    | 81.79306 |      90.56132     | 196.0033 |      193.4111     |   Changed Both   |
|     9    | 94.71505 |      104.8044     | 215.0758 |      224.6175     |   Changed Both   |

Tidak ada perubahan

Jumlah Fitur yang Bertambah Linier

Meningkatkan Sampel secara Linier

Meningkatkan Sampel + Fitur Linier

Saat saya mulai meneliti lebih banyak; ini masuk akal. GPU dikenal untuk menskalakan dengan baik dengan data dimensi tinggi, dan masuk akal jika Anda melihat peningkatan waktu pelatihan jika data Anda berdimensi tinggi . Lihat contoh berikut:

  • https://projecteuclid.org/download/pdfview_1/euclid.ss/1294167962
  • Kmeans Lebih Cepat Mengelompokkan Data Dimensi Tinggi dengan Dukungan GPU
  • https://link.springer.com/article/10.1007/s11063-014-9383-4

Meskipun kami tidak dapat mengatakan dengan pasti tanpa akses ke data Anda, tampaknya kapabilitas perangkat keras dari GPU memungkinkan peningkatan kinerja yang signifikan ketika data Anda mendukungnya, dan tampaknya bukan itu masalahnya mengingat ukuran dan bentuk data Anda. memiliki.