Как ограничить количество процессоров, используемых скриптом Python без терминала или многопроцессорной библиотеки? - PullRequest
1 голос
/ 18 апреля 2019

Моя главная проблема выдается здесь .Поскольку никто еще не дал решения, я решил найти обходной путь.Я ищу способ ограничить использование процессора скриптами Python ( не приоритет, но количество ядер процессора ) с помощью кода Python.Я знаю, что могу сделать это с многопроцессорной библиотекой (пул и т. Д.), Но я не тот, кто запускает ее с многопроцессорной обработкой.Итак, я не знаю, как это сделать.И также я мог бы сделать это через терминал, но этот скрипт импортируется другим скриптом.К сожалению, я не могу позволить себе звонить через терминал.

tl; dr: Как ограничить использование процессора ( количество ядер ) скрипта python, который импортируется другим скриптом, и я даже не знаю, почему он работает параллельнобез запуска через терминал.(Пожалуйста, проверьте фрагмент кода ниже, и да, английский не мой родной язык)

Фрагмент кода, вызывающий проблему:

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA
import numpy as np

X, _ = load_digits(return_X_y=True)

#Copy-paste and increase the size of the dataset to see the behavior at htop.
for _ in range(8):
    X = np.vstack((X, X))

print(X.shape)

transformer = IncrementalPCA(n_components=7, batch_size=200)

#PARTIAL FIT RUNS IN PARALLEL! GOD WHY?
---------------------------------------
transformer.partial_fit(X[:100, :])
---------------------------------------
X_transformed = transformer.fit_transform(X)

print(X_transformed.shape)

Версии:

  • Python3.6
  • joblib 0.13.2
  • scikit-learn 0.20.2
  • numpy 1.16.2

ОБНОВЛЕНИЕ: неРабота.Спасибо за разъяснения @Darkonaut.Печально то, что я уже знал, что это не сработает, и я уже четко указал название вопроса, но люди не читают, я думаю. Полагаю, я делаю это неправильно.Я обновил фрагмент кода на основе @Ben Chaliah Ayoub answer .Кажется, ничего не изменилось.И еще я хочу указать на кое-что: я не пытаюсь запустить этот код на нескольких ядрах.Эта строка transformer.partial_fit(X[:100, :]) работает на нескольких ядрах (по некоторым причинам) и не имеет n_jobs или чего-либо еще.Также обратите внимание, что мой первый пример и мой оригинальный код не инициализированы с пулом или чем-то подобным.Я не могу установить количество ядер в первую очередь (потому что такого места нет).Но теперь есть место для этого, но он все еще работает на нескольких ядрах.Не стесняйтесь проверить это самостоятельно.(Код ниже) Вот почему я ищу обходной путь.

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA
import numpy as np
from multiprocessing import Pool, cpu_count
def run_this():
    X, _ = load_digits(return_X_y=True)
    #Copy-paste and increase the size of the dataset to see the behavior at htop.
    for _ in range(8):
        X = np.vstack((X, X))
    print(X.shape)
    #This is the exact same example taken from sckitlearn's IncrementalPCA website.
    transformer = IncrementalPCA(n_components=7, batch_size=200)
    transformer.partial_fit(X[:100, :])
    X_transformed = transformer.fit_transform(X)
    print(X_transformed.shape)
pool= Pool(processes=1)
pool.apply(run_this)

ОБНОВЛЕНИЕ: Итак, я попытался установить потоки blas, используя this в моем коде, прежде чем импортировать numpy, но это не сработало (снова).Любые другие предложения?Последнюю стадию кода можно найти ниже.

Кредиты: @ Amir

from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA
import os
os.environ["OMP_NUM_THREADS"] = "1" # export OMP_NUM_THREADS=1
os.environ["OPENBLAS_NUM_THREADS"] = "1" # export OPENBLAS_NUM_THREADS=1
os.environ["MKL_NUM_THREADS"] = "1" # export MKL_NUM_THREADS=1
os.environ["VECLIB_MAXIMUM_THREADS"] = "1" # export VECLIB_MAXIMUM_THREADS=1
os.environ["NUMEXPR_NUM_THREADS"] = "1" # export NUMEXPR_NUM_THREADS=1

import numpy as np

X, _ = load_digits(return_X_y=True)

#Copy-paste and increase the size of the dataset to see the behavior at htop.
for _ in range(8):
    X = np.vstack((X, X))

print(X.shape)
transformer = IncrementalPCA(n_components=7, batch_size=200)

transformer.partial_fit(X[:100, :])

X_transformed = transformer.fit_transform(X)

print(X_transformed.shape)

Ответы [ 2 ]

1 голос
/ 14 мая 2019

Я решил проблему в примере кода, приведенном в исходном вопросе, установив переменные среды BLAS (из это ссылка). Но это не ответ на мой настоящий вопрос. Моя первая попытка (второе обновление) была неверной. Мне нужно было установить количество потоков не перед импортом библиотеки numpy, а перед импортом библиотеки (IncrementalPCA) .
Итак, в чем была проблема в примере кода? Это была не проблема, а особенность библиотеки BLAS, используемой библиотекой numpy. Попытка ограничить его с помощью многопроцессорной библиотеки не сработала, потому что по умолчанию OpenBLAS настроен на использование всех доступных потоков.
Кредиты: @ Амир и @Darkonaut Источники : OpenBLAS 1 , OpenBLAS 2 , Решение

import os
os.environ["OMP_NUM_THREADS"] = "1" # export OMP_NUM_THREADS=1
os.environ["OPENBLAS_NUM_THREADS"] = "1" # export OPENBLAS_NUM_THREADS=1
os.environ["MKL_NUM_THREADS"] = "1" # export MKL_NUM_THREADS=1
os.environ["VECLIB_MAXIMUM_THREADS"] = "1" # export VECLIB_MAXIMUM_THREADS=1
os.environ["NUMEXPR_NUM_THREADS"] = "1" # export NUMEXPR_NUM_THREADS=1
from sklearn.datasets import load_digits
from sklearn.decomposition import IncrementalPCA


import numpy as np

X, _ = load_digits(return_X_y=True)

#Copy-paste and increase the size of the dataset to see the behavior at htop.
for _ in range(8):
    X = np.vstack((X, X))

print(X.shape)
transformer = IncrementalPCA(n_components=7, batch_size=200)

transformer.partial_fit(X[:100, :])

X_transformed = transformer.fit_transform(X)

print(X_transformed.shape)

Но вы можете явно установить правильную среду BLAS, проверив, какая из них используется вашей numpy сборкой так:

>>>import numpy as np
>>>np.__config__.show()

** Дали эти результаты ... **

blas_mkl_info:
  NOT AVAILABLE
blis_info:
  NOT AVAILABLE
openblas_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
blas_opt_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
lapack_mkl_info:
  NOT AVAILABLE
openblas_lapack_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
lapack_opt_info:
    libraries = ['openblas', 'openblas']
    library_dirs = ['/usr/local/lib']
    language = c
    define_macros = [('HAVE_CBLAS', None)]

... означает, что OpenBLAS используется моей numpy сборкой. И все, что мне нужно написать, это os.environ["OPENBLAS_NUM_THREADS"] = "2" , чтобы ограничить использование потоков библиотекой numpy.

0 голосов
/ 18 апреля 2019

Я ищу способ ограничить использование процессора скриптами Python (не приоритетом, а числом ядер процессора) с помощью кода Python.

Запустите ваше приложение с taskset. Например, чтобы ограничить количество используемых процессоров 4, выполните:

taskset --cpu-list 0,1,2,3 <app>
...