KMCUDA: GPU/CUDA реализует Kmeans

GPU
  • В последнее время в проекте используется алгоритм Kmeans.Учитывая ограничение скорости реализации ЦП, необходимо использовать ускорение графического процессора, поэтому установлено, чтоlibKMCUDAбиблиотека.
  • Запишите некоторые проблемы, возникающие при установке и использовании.

1. Введение в kmcuda

адрес проекта:kmcuda

Содержание проекта: Крупномасштабная реализация K-means и K-nn на NVIDIA GPU / CUDA

Подробное знакомство с проектом см.githubописание выше.

Производительность выглядит следующим образом:

Технически проект представляет собой разделяемую библиотеку, которая экспортируетkmcuda.hДве функции, определенные в :kmeasn_cudaиknn_cuda. Он имеет встроенную поддержку расширений языка Python3 и R, поэтому его можно загрузить сlibKMCUDAИмпортироватьkmeans_cudaилиdyn.load("libKMCUDA.so").

2. Установка

GithubКоманда установки, приведенная выше:

git clone https://github.com/src-d/kmcuda
cd src
cmake -DCMAKE_BUILD_TYPE=Release . && make

Есть несколько параметров, на которые стоит обратить внимание:

  • -D DISABLE_PYTHON: если вы не хотите компилироватьPythonМодуль поддержки, установите это значение какy, то есть увеличить-D DISABLE_PYTHON=y

  • -D DISABLE_R: если вы не хотите компилироватьRМодули поддержки, добавить-D DISABLE_R=y

  • -D CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-10.0(修改为自己的路径):еслиCUDAЕсли он не может быть найден автоматически, добавьте этот элемент

  • -D CUDA_ARCH=52: укажите вычислительные возможности CUDA текущей машины (вычислительные возможности графического процессора).

  • gcc: В статье упоминалось, что младшая версия компилятора gcc не поддерживает его.Моя текущая версия 5.4, которая может удовлетворить потребности.

1. Запросить версию gcc

Если версия слишком низкая, вы можете установить gcc-5.4. Для конкретной установки обратитесь к следующему сообщению в блоге:

Подробная установка gcc под linux

2. Запросить вычислительную мощность графического процессора

Проверьте вычислительную мощность графического процессора вашего графического сервера на официальном веб-сайте NVIDIA по следующему адресу:

CUDA GPUs | NVIDIA Developer

Сервер, который я сейчас использую,GeForce RTX 2070, соответствующая вычислительная мощность равна7.5. следовательно,CUDA_ARCHустановить на 75,-D CUDA_ARCH=75

3. Настройте путь графического процессора

Чтобы иметь возможность автоматически находить путь к нужной библиотеке, установитеcudaПуть настраивается в файле конфигурации. Оболочка, используемая текущей системой,zsh:

существует~/.zshrcДобавьте следующие элементы в:

export PATH=$PATH:/usr/local/cuda/bin
export LD_LIBRARAY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
export CUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda:$CUDA_TOOLKIT_BOOT_DIR
export CUDA_INCLUDE_DIRS=/usr/local/cuda/include

Активация вступает в силу:

source ~/.zshrc

3. Выполните команду установки

Текущие параметры оборудования:

  • gcc: версия 5.4
  • Вычислительная мощность графического процессора: 7,5
  • Требуется только поддержка версии Python

Полная команда установки:

git clone https://github.com/src-d/kmcuda
cd src
cmake -DCMAKE_BUILD_TYPE=Release -D DISABLE_R-y -D CUDA_ARCH=75 . && make

контрольная работа:

4. Проблемы, возникающие при установке

1. Установить с помощью pip

Команда установки выглядит следующим образом:

CUDA_ARCH=75 pip install libKMCUDA

Произошла ошибка:

2. Не указывайте вычислительную мощность графического процессора или используйте значение по умолчанию.

  • Установить исходные файлы с помощью pip

    Команда установки:

    pip install git+https://github.com/src-d/kmcuda.git#subdirectory=src

    Возникает следующая ошибка:

    Эту ошибку можно увидеть, используя этот метод для установки, по умолчанию используется-DCUDA_ARCH61 год, что не соответствует действительности.

  • Вычислительная мощность графического процессора не указана

    Команда установки:

    cmake -DCMAKE_BUILD_TYPE=Release -D DISABLE_R=y . && make

    Как показано на рисунке ниже, установка прошла успешно

При тестировании возникает следующая ошибка:

Указывает, что вычислительная мощность не соответствует устройству.

5. Тестовые примеры Python

1. K-means, L2 (Euclidean) distance

import numpy
from matplotlib import pyplot
from libKMCUDA import kmeans_cuda

numpy.random.seed(0)
arr = numpy.empty((10000, 2), dtype=numpy.float32)
arr[:2500] = numpy.random.rand(2500, 2) + [0, 2]
arr[2500:5000] = numpy.random.rand(2500, 2) - [0, 2]
arr[5000:7500] = numpy.random.rand(2500, 2) + [2, 0]
arr[7500:] = numpy.random.rand(2500, 2) - [2, 0]
centroids, assignments = kmeans_cuda(arr, 4, verbosity=1, seed=3)
print(centroids)
pyplot.scatter(arr[:, 0], arr[:, 1], c=assignments)
pyplot.scatter(centroids[:, 0], centroids[:, 1], c="white", s=150)
pyplot.show()

2. K-means, angular (cosine) distance + average

import numpy
from matplotlib import pyplot
from libKMCUDA import kmeans_cuda

numpy.random.seed(0)
arr = numpy.empty((10000, 2), dtype=numpy.float32)
angs = numpy.random.rand(10000) * 2 * numpy.pi
for i in range(10000):
    arr[i] = numpy.sin(angs[i]), numpy.cos(angs[i])
centroids, assignments, avg_distance = kmeans_cuda(
    arr, 4, metric="cos", verbosity=1, seed=3, average_distance=True)
print("Average distance between centroids and members:", avg_distance)
print(centroids)
pyplot.scatter(arr[:, 0], arr[:, 1], c=assignments)
pyplot.scatter(centroids[:, 0], centroids[:, 1], c="white", s=150)
pyplot.show()

Результат выглядит следующим образом:

6. API-интерфейс Python

1. kmeans_cuda()

def kmeans_cuda(samples, clusters, tolerance=0.01, init="k-means++",
                yinyang_t=0.1, metric="L2", average_distance=False,
                seed=time(), device=0, verbosity=0)

параметр:

  • samples: массив numpy с формой [количество выборок, количество функций] или кортеж (необработанный указатель устройства (int), индекс устройства (int)
    • Примечание: «образцы» должны быть двумерными массивами float32 или float16 numpy.
  • clusters: intтип, количество кластеров
    • Примечание: «кластеры» должны быть больше 1 и меньше (1
  • tolerance:floatалгоритм останавливается, если относительная сумма перераспределения падает ниже этого значения.
  • init:stringили массив numpy, установите метод инициализации центроида, который может бытьk-means++,afk-mc2,randomИли массив numpy указанной формы [кластер, количество признаков], тип должен бытьfloat32
  • yinynag_t:floatтип, обычно устанавливается равным 0,1
  • metric:strТип, имя используемой метрики расстояния. По умолчаниюDuclidean(L2), который можно изменить наcos. Обратите внимание, что в последнем случае образцы должны быть нормализованы.
  • average_distance:booleanType, это значение указывает, следует ли вычислять среднее расстояние между элементами в классе и соответствующими центроидами, полезное для нахождения оптимального K, возвращенного как третий элемент кортежа.
  • seed:intType, начальное число генератора случайных чисел, используемое для воспроизведения результатов.
  • device:intТип, индекс устройства CUDA, например 1 для первого устройства, 2 для второго и 3 для использования первого и второго. Укажите 0, чтобы включить все устройства, по умолчанию 0.
  • verbosity:intТип, 0 означает отсутствие вывода, 1 означает только ведение журнала, 2 означает много вывода.

возвращаемое значение: кортеж(centroids, assignments, [average_distance]). еслиsamplesпредставляет собой кортеж указателя хоста с четным массивом numpy, тип представляет собой массив numpy, в противном случае необработанный указатель (целое число) размещается на том же устройстве. еслиsamplesдаfloat16, то возвращаемый центроид такжеfloat16.

2. knn_cuda()

def knn_cuda(k, samples, centroids, assignments, metric="L2", device=0, verbosity=0)

параметр:

  • k: целое число, количество соседей для поиска каждой выборки. Должно быть ≤ 116.

  • samples: пустой массив формы [количество выборок, количество функций] или кортеж (необработанный указатель устройства (int), индекс устройства (int), форма (кортеж (количество выборок, количество функций [ маркер fp16x2]))). В последнем случае отрицательный индекс устройства означает указатель хоста. При необходимости кортеж может быть на 1 элемент длиннее с предварительно выделенным указателем устройства для соседей. Тип dtype должен быть либо с плавающей точкой16, либо с возможностью преобразования в число с плавающей запятой32.

  • centroids: массив numpy с предварительно рассчитанными центроидами кластеров (например, с использованием K-means/kmcuda/kmeans_cuda()). Тип dtype должен соответствовать сэмплам. Если сэмплы — кортеж, то центроиды должны быть кортежем длины 2, первый элемент — указатель, а второй - количество кластеров Форма (количество кластеров, количество признаков).

  • assignments: массив numpy с ассоциациями выборки-кластера. Ожидается, что dtype будет совместим с uint32. Если образцы - это кортеж, то назначения - это указатель. Форма (количество выборок).

  • metric: str, имя используемой метрики расстояния. По умолчанию используется евклидово (L2), его можно изменить на «cos», чтобы изменить алгоритм на сферические K-средние с угловым расстоянием. Обратите внимание, что выборки должны быть нормализованы в последний случай.

  • device: целое число, индексы устройств CUDA с побитовым ИЛИ, например, 1 означает первое устройство, 2 означает второе устройство, 3 означает использование первого и второго устройств. Специальное значение 0 включает все доступные устройства. Значение по умолчанию — 0.

  • verbosity: целое число, 0 означает полную тишину, 1 означает просто регистрацию прогресса, 2 означает много вывода.

возвращаемое значение: соседние индексы. Если образцы были пустым массивом или кортежем указателя хоста, тип возвращаемого значения — пустой массив, в противном случае — необработанный указатель (целое число), размещенный на том же устройстве. Форма (количество выборок, k).