New POC: AI Training, Inference, (Software in VDI)aaS
OVHcloud will offer a large range of the products AI/DL+ML based on GPU/CPU/FPGA/Optical.







Облачные технологии — это не только хранение данных, но и выполнение любых сложных вычислений и подобных задач. В ближайшем будущем удалённые рабочие столы, способные не просто работать с документами и базами данных, а заниматься высоконагруженными проектами, будут востребованы всё больше. Хостинг-провайдер REG.RU готов предоставлять такие услуги уже сейчас. Обучайте нейросети, совершайте масштабные вычисления, обрабатывайте графику на GPU-сервисе от REG.RUкомментирует генеральный директор REG.RU Алексей Королюк.



Облачные вычисления на GPU — это во многом эксперимент, который показал отличные результаты! В течение года мы тестировали продукт, предоставляли его участникам хакатонов, изучали спрос и отклики. Разработка понятной и устойчивой тарифной сетки и выход в открытое бета-тестирование — это ещё один шаг в развитии нашей услугикомментирует генеральный директор REG.RU Алексей Королюк.
Мощные вычислительные платформы сегодня востребованы не только в сфере исследований, но и в бизнесе. Доступ к вычислениям в облаке и наличие необходимых программных инструментов обеспечивают компании разного масштаба всеми необходимыми ресурсами для реализации самых смелых идейотмечает Дмитрий Конягин, руководитель направления Enterprise-решений в NVIDIA Россия






ssh root@[YOUR GPU INSTANCE IP ADDRESS]nvidia-docker run -it rg.fr-par.scw.cloud/opetrova/frontalization:tutorial
root@b272693df1ca:/Frontalization# ls
Dockerfile data.py main.py network.py test.py training_setconda install -y python==3.6.7
conda install -y pytorch torchvision
pip install --extra-index-url https://developer.download.nvidia.com/compute/redist nvidia-dali==0.6.1scp -r path/to/local/training_set root@[YOUR GPU INSTANCE IP ADDRESS]:/root/Frontalization
import collections
from random import shuffle
import os
from os import listdir
from os.path import join
import numpy as np
from nvidia.dali.pipeline import Pipeline
import nvidia.dali.ops as ops
import nvidia.dali.types as types
def is_jpeg(filename):
return any(filename.endswith(extension) for extension in [".jpg", ".jpeg"])
def get_subdirs(directory):
subdirs = sorted([join(directory,name) for name in sorted(os.listdir(directory)) if os.path.isdir(os.path.join(directory, name))])
return subdirs
flatten = lambda l: [item for sublist in l for item in sublist]
class ExternalInputIterator(object):
def __init__(self, imageset_dir, batch_size, random_shuffle=False):
self.images_dir = imageset_dir
self.batch_size = batch_size
# First, figure out what are the inputs and what are the targets in your directory structure:
# Get a list of filenames for the target (frontal) images
self.frontals = np.array([join(imageset_dir, frontal_file) for frontal_file in sorted(os.listdir(imageset_dir)) if is_jpeg(frontal_file)])
# Get a list of lists of filenames for the input (profile) images for each person
profile_files = [[join(person_dir, profile_file) for profile_file in sorted(os.listdir(person_dir)) if is_jpeg(profile_file)] for person_dir in get_subdirs(imageset_dir)]
# Build a flat list of frontal indices, corresponding to the *flattened* profile_files
# The reason we are doing it this way is that we need to keep track of the multiple inputs corresponding to each target
frontal_ind = []
for ind, profiles in enumerate(profile_files):
frontal_ind += [ind]*len(profiles)
self.frontal_indices = np.array(frontal_ind)
# Now that we have built frontal_indices, we can flatten profile_files
self.profiles = np.array(flatten(profile_files))
# Shuffle the (input, target) pairs if necessary: in practice, it is profiles and frontal_indices that get shuffled
if random_shuffle:
ind = np.array(range(len(self.frontal_indices)))
shuffle(ind)
self.profiles = self.profiles[ind]
self.frontal_indices = self.frontal_indices[ind]
def __iter__(self):
self.i = 0
self.n = len(self.frontal_indices)
return self
# Return a batch of (input, target) pairs
def __next__(self):
profiles = []
frontals = []
for _ in range(self.batch_size):
profile_filename = self.profiles[self.i]
frontal_filename = self.frontals[self.frontal_indices[self.i]]
profile = open(profile_filename, 'rb')
frontal = open(frontal_filename, 'rb')
profiles.append(np.frombuffer(profile.read(), dtype = np.uint8))
frontals.append(np.frombuffer(frontal.read(), dtype = np.uint8))
profile.close()
frontal.close()
self.i = (self.i + 1) % self.n
return (profiles, frontals)
next = __next__
class ImagePipeline(Pipeline):
'''
Constructor arguments:
- imageset_dir: directory containing the dataset
- image_size = 128: length of the square that the images will be resized to
- random_shuffle = False
- batch_size = 64
- num_threads = 2
- device_id = 0
'''
def __init__(self, imageset_dir, image_size=128, random_shuffle=False, batch_size=64, num_threads=2, device_id=0):
super(ImagePipeline, self).__init__(batch_size, num_threads, device_id, seed=12)
eii = ExternalInputIterator(imageset_dir, batch_size, random_shuffle)
self.iterator = iter(eii)
self.num_inputs = len(eii.frontal_indices)
# The source for the inputs and targets
self.input = ops.ExternalSource()
self.target = ops.ExternalSource()
# nvJPEGDecoder below accepts CPU inputs, but returns GPU outputs (hence device = "mixed")
self.decode = ops.nvJPEGDecoder(device = "mixed", output_type = types.RGB)
# The rest of pre-processing is done on the GPU
self.res = ops.Resize(device="gpu", resize_x=image_size, resize_y=image_size)
self.norm = ops.NormalizePermute(device="gpu", output_dtype=types.FLOAT,
mean=[128., 128., 128.], std=[128., 128., 128.],
height=image_size, width=image_size)
# epoch_size = number of (profile, frontal) image pairs in the dataset
def epoch_size(self, name = None):
return self.num_inputs
# Define the flow of the data loading and pre-processing
def define_graph(self):
self.profiles = self.input(name="inputs")
self.frontals = self.target(name="targets")
profile_images = self.decode(self.profiles)
profile_images = self.res(profile_images)
profile_output = self.norm(profile_images)
frontal_images = self.decode(self.frontals)
frontal_images = self.res(frontal_images)
frontal_output = self.norm(frontal_images)
return (profile_output, frontal_output)
def iter_setup(self):
(images, targets) = self.iterator.next()
self.feed_input(self.profiles, images)
self.feed_input(self.frontals, targets)from __future__ import division
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
%matplotlib inline
def show_images(image_batch, batch_size):
columns = 4
rows = (batch_size + 1) // (columns)
fig = plt.figure(figsize = (32,(32 // columns) * rows))
gs = gridspec.GridSpec(rows, columns)
for j in range(rows*columns):
plt.subplot(gs[j])
plt.axis("off")
plt.imshow(np.transpose(image_batch.at(j), (1,2,0)))
batch_size = 8
pipe = ImagePipeline('my_dataset_directory', image_size=128, batch_size=batch_size)
pipe.build()
profiles, frontals = pipe.run()
# The images returned by ImagePipeline are currently on the GPU
# We need to copy them to the CPU via the asCPU() method in order to display them
show_images(profiles.asCPU(), batch_size=batch_size)
show_images(frontals.asCPU(), batch_size=batch_size)








Линия графика, выделенная оранжевым, показывает время, которое требуется для создания данных в обычном ОЗУ, передачу их в память GPU и последующие вычисления. Зеленая линия показывает время, которое требуется на вычисление данных, которые были сгенерированы уже в памяти видеокарты (без передачи из ОЗУ). Синяя отображает время подсчета на центральном процессоре. Матрицы порядка менее 1000 элементов перемножаются на GPU и CPU почти за одинаковое время. Разница в производительности хорошо проявляется с матрицами размерами более 2000 на 2000, когда время вычислений на CPU подскакивает до 1 секунды, а GPU остается близким к нулю.



Машинное обучение из удела немногих одержимых исследователей превращается в ещё один инструмент рядового разработчика. Раньше (например в 2012) люди писали низкоуровневый код для обучения сверточных сетей на паре видеокарт. Сейчас, кто угодно может за считанные часы

Присоединенные к GPU узлы вместе с Kubernetes обеспечивают мощную, экономичную и гибкую среду для машинного обучения на уровне предприятия. Ocado выбрала Kubernetes за ее масштабируемость, мобильность, сильную экосистему и огромную поддержку сообщества. Он легче, гибче и удобнее в обслуживании по сравнению с кластером традиционных виртуальных машин. Он также имеет большую простоту в использовании и возможность прикреплять аппаратные ускорители, такие как графические процессоры и TPU, обеспечивая огромный прирост по сравнению с традиционными процессорами— Мартин Николов, инженер-разработчик программного обеспечения, Ocado
