УДК 004
ПАРАЛЛЕЛЬНЫЙ ПОДХОД К РЕШЕНИЮ ЗАДАЧИ ОДНОМЕРНОЙ ПРОДОЛЖЕННОЙ УПАКОВКИ (1CBPP)
С ИСПОЛЬЗОВАНИЕМ ТЕХНОЛОГИИ CUDA
© В. М. Картак*, А. В. Рипатти
Уфимский государственный авиационный технический университет Россия, Республика Башкортостан, 450000 г. Уфа, ул. К. Маркса, 12.
E-mail: kvmail@mail.ru
Рассматривается задача одномерной продолженной упаковки (1CBPP). Для ее решения предлагается параллельный алгоритм, основанный на методе ветвей и границ. Алгоритм адаптирован к выполнению на графических видеокартах с поддержкой технологии CUDA.
Ключевые слова: одномерная продолженная упаковка, метод ветвей и границ, параллельные вычисления, GPGPU, CUDA.
Введение
Задача одномерной продолженной упаковки (1D Continuous Bin Packing Problem, 1CBPP) состоит определении минимального количества одномерных контейнеров длины W, в которые необходимо разместить предметы n типов заданной длины wi, удовлетворяя потребности bi (1 < i < n) с соблюдением последовательности загрузки контейнеров при их упаковке. Предметы каждого типа должны содержаться в смежных контейнерах (нет таких двух контейнеров, содержащих предмет данного типа, что имеется между ними третий контейнер без предмета данного типа). Последовательность контейнеров - фиксированная.
Эта задача исследовалась различными авторами [1]. В литературе она так же известна как задача одномерной прямоугольно ориентированной упаковки (1D Rectangular Oriented Cutting Stock Problem, 1ROCSP), которая используется в блочной технологии для решения задачи двухмерной упаковки в полосу (2D Strip Packing Problem, 2SPP) [2]. В работе [3] показано, что решение задачи 1CBPP является нижней границей решения задачи 2DPP. В ряде случаев из решения задачи 1CBPP удается получить оптимальное решение задачи 2DPP [4]. Задача 1CBPP также имеет применение в задачах теории расписаний, например, как задача расписания ресурсов [5].
Задача 1CBPP является NP-трудной. В качестве точных методов решения используются метод ветвей и границ, методы линейного программирования, а также их комбинации [1, 2, 4, 6].
В данной работе рассмотрен параллельный подход решения задачи 1CBPP. Распараллеливание вычислений является одним из способов ускорения решения различных задач. Однако только увеличение числа процессоров не приводит к увеличению производительности. Для эффективного распараллеливания нужно придумать способ разбиения задачи на информационно-независимые подзадачи, которые распределяются между процессорами так, чтобы нагрузка на каждый из них была примерно одинакова.
В качестве программно-аппаратных средств параллельных вычислений выбраны графические видеокарты фирмы Nvidia с поддержкой техноло-
гии CUDA. Выбор обусловлен высоким отношением производительности видеокарты к ее стоимости, а также наличием подробной документации.
Архитектура CUDA вносит дополнительные ограничения на алгоритм решения задачи. Например, согласно принципу SIMD (Single Instruction Multiple Data), все процессоры должны выполнять один и тот же алгоритм, а число ветвлений в алгоритме должно быть сведено к минимуму.
Статья имеет следующую структуру. В разделе 1 дана математическая модель задачи 1CBPP. Раздел 2 описывает способ сокращения пространства рассматриваемых решений, основанный на отображении множества допустимых решений на множество перестановок. В разделе 3 описан точный параллельный алгоритм решения задачи 1CBPP с учетом ограничений архитектуры CUDA. Вычислительные результаты реализации данного алгоритма представлены в разделе 4.
1. Математическая модель задачи 1CBPP В данном разделе словесное описание задачи, приведенное во введении, записывается формально в виде математической модели. В конце раздела приведен пример.
Дано:
Четверка < W, n, w, b >, где
• W - целое число, W > 0 .
• n - целое число, n > 0 .
• w - вектор целых чисел (Wj, W2,l, wn ), все 0 < wi < W .
• b - вектор целых чисел (bj, b2,L, bn),
b >0.
Требуется:
Найти решение - вектор s = (s1, s2, • • •, sn) (все si -целые числа, > 0) такой, что
T(s) = max (si + bi) ^ min,
1<i<n
При условии:
^ wt < W для Vt є {0,1, •••,max(si + bi) -1},
ieK (t)
где K(x) = {i: s{ < x < s{ + bt}.
* автор, ответственный за переписку
Вектор s описывает решение задачи 1CBPP. Присвоим последовательно каждому контейнеру номер начиная с нуля. Очевидно, для каждого типа предметов достаточно указать наименьший номер контейнера, в который был упакован предмет данного типа. Для i-го типа это число равно st.
Введем функцию T(s), обозначающую количество контейнеров, которое требуется для упаковки всех предметов в решении s .
За OPT обозначим оптимальное решение задачи: OPT = argminsf,ST(s), где S - множество всех решений. OPT всегда существует.
На рис. 1 показан пример решения задачи 1CBPP.
Рис. 1. Одно из оптимальных решений задачи при W = 5, n = 8, w = (2,3,1,2,1,1,3,2), b = (3,2,3,4,3,2,2,3): OPT = (0,0,2,2,3,3,6,5), T(OPT) = 8.
2. Сокращение пространства решений
В разделе рассматривается способ сокращения числа рассматриваемых решений путем кодирования решений при помощи перестановок. Перестановка длины n - это последовательность из n различных целых чисел из диапазона [1... n]. Число перестановок длины n равно n! - именно этим числом и будет ограничиваться количество решений для рассмотрения.
В конце раздела рассматривается кодирование перестановки целым числом, а также обратное преобразование. Этот прием позволяет сократить объем данных, которые нужно будет посылать на видеокарту.
Пусть S - множество всех решений, а P -множество всех перестановок чисел от 1 до n. Определим функцию f : S ^ P следующим образом. Упорядочим все n типов предметов по номеру контейнера, в котором находится самый левый предмет данного типа. При равенстве номеров контейнеров упорядочим типы по возрастанию номеров. Итоговой перестановкой будет последовательность номеров типов после упорядочивания.
f ({sp S2,L , Sn }) = { Pv P2,L , Pn }
SP. < Sp, или sPi = Sp,,Pi < Pj, для 1 < i < j < n.
Определим функцию g : p ^ S с помощью правила Next Fit (NF). Его суть заключается в том, что группа предметов каждого типа укладывается, начиная с как можно более левого контейнера, в который может поместиться предмет данного типа,
но не левее, чем первый предмет предыдущего типа:
g ({ Pv P2,L, Pn }) = {sp S2,' '', Sn },
s1 = 0,
st = min{x : x > si-1, ^ wj < W - wt}, для 2 < i < n,
jeK (x)
где K(x) = {k : sk < x < sk + bk ,1 < k < i}. Отметим, что ни f, ни g не являются биекциями; g(f (s)) = s лишь для некоторых s є S , однако f (g(p)) = p для любого P є P .
Утверждение 1. Vs є S : T(g (f (s))) < T(s).
Доказательство. Пусть s' = g(f (s)).
Покажем, что sj < s. для всех 1 < i < n , методом математической индукции. Для i = 1 утверждение, очевидно, выполняется. Предположим, что для
некоторого 2 < k < n все неравенства вида si < s j выполняются для любого 1 < j < k . Тогда, исходя из определения правила NF, s'k < sk .
Поскольку sj < st для всех 1 < i < n , то T(s') < T(s) по определению функции T. ■
Следствие. Зр є P: T(g(р)) = T(OPT).
Таким образом, для решения задачи 1CBPP необходимо перебрать все перестановки длины n. Для каждой из них с помощью правила NF сгенерировать решение и выбрать наилучшее. Всего перестановок n!, правило NF можно реализовать за O(n2), тогда оценка сложности алгоритма сверху -
O(n!n2 ) .
Для передачи перестановок графической видеокарте для проверки удобно кодировать перестановки целыми числами.
Обозначим через F множество целых чисел от
0 до n!-1 . Отсортируем все перестановки лексикографически (р < р если Зі : р} = pj для 1 < j < i,
р■ < р') и занумеруем их последовательными числами от 0 до n!-1. Данное взаимно-однозначное соответствие дает нам две функции encode : P ^ F и decode : F ^ P . Обе эти функции можно реализовать за O(n2 ) .
З. Модификация метода ветвей и границ
В данном разделе описан параллельный алгоритм решения задачи 1CBPP. Этот алгоритм является модификацией метода ветвей и границ. Его мысленно можно разбить на две части: перебор на CPU и вычисления на GPU. Перебор на CPU последовательно обходит верхние слои дерева перебора только до определенной заранее заданной глубины. Для сокращения перебора используются различные отсечения. Самые глубокие достигнутые вершины сохраняются в очередь - каждая из этих вершин задает поддерево перебора заранее известного размера. Как только число вершин в очереди станет достаточно большим - все они засылаются на GPU, где обрабатываются параллельно.
Опишем этап перебора на CPU. Будем рекурсивно строить перестановку так, чтобы на d-м уровне глубины рекурсии был построен префикс перестановки длины d.
В процессе обхода будем строить частичные решения в соответствии с алгоритмом NF и отсекать ветви следующими правилами, описанными в [6]:
• Исключение вертикально эквивалентных решений. Если для текущей глубины рекурсии d sd = sd_1 и Pd < Pd , то завершаем обработку ветви, поскольку если поменять Pd и P -1 местами, получим то же самое.
• Исключение улучшаемых решений. Если текущую группу предметов можно подвинуть левее хотя бы на один контейнер относительно предыдущей группы (тем самым получив решение не хуже), то завершаем обработку ветви.
Пусть мы рекурсивно спустились в дереве поиска на глубину n — h . Теперь мы находимся в корне дерева высотой h, у данного дерева имеется h! листьев. Каждый лист соответствует перестановке, а номера этих перестановок образуют отрезок [ z ^ z + h!—1], где z = encode (Pt), а p - переста-
новка, соответствующая самому левому листу в текущем поддереве. Если принять число к за константу, то данное множество перестановок можно закодировать одним числом - z . Именно это число мы и будем пересылать видеокарте. В качестве ответа будем принимать число ^ ^ [z••• z + к!-1] -номер перестановки, на которой достигается минимум функции Т.
В силу особенностей архитектуры СиЭЛ, мы не можем сразу отправлять не проверку только что полученное число z . Вместо этого мы создадим очередь q, в которую будем помещать числа z каждого из достигнутых поддеревьев высоты к. Как только размер очереди станет равным к, где к -число потоков, отправим все числа из очереди на проверку. Каждый поток будет обрабатывать свою версию числа z, при этом все потоки будут действовать параллельно по одному и тому же алгоритму. А именно: генерировать все перестановки из заданного диапазона, строить для них решения и вычислять значение функции Т. Такой подход хорошо ложится на архитектуру СиЭЛ: мало ветвлений, все потоки делают одно и то же.
Рис. 2. Дерево перебора перестановок.
Рис. 3. Вертикально эквивалентные решения.
Рис. 4. Улучшаемые решения.
После окончания перебора в очереди q могут еще остаться числа - их также следует отправить на обработку видеокарте.
Теперь рассмотрим этап вычислений на GPU. Каждый поток на вход получает число z, после чего в цикле перебирает h! перестановок и находит число z =argminxE[Lz+h!—1]{T(g(decode(x)))b которое затем и возвращает.
Таким образом, решение схематично выглядит
так:
thread_kernel( z ) // код для одного потока
1 z ^ z, m <—
2 цикл i ^ z ••• z + h!—1
3 m ^ T(g (decode (i)))
4 если m < m, то
5 z ^ i, m ^ m
6 return z
dfs_device( d ) // рекурсивная генерация перестановки 1
2
3
4
5
6
7
8
9
10
если d = n — h, то
добавить в очередь q число z = encode (p)
если размер очереди q равен к , то запустить thread_kernel для всей очереди q определить и сохранить лучшее найденное решение
очистить очередь q иначе
цикл - перебор значений pd если не сработали отсечения dfs_device( d +1)
main_device( г ) // главная функция
1 dfs_device (1)
2 запустить thread_kernel для всей очереди ^ определить и сохранить лучшее найденное решение
вывести лучшее найденное решение
4. Результаты вычислений
В эксперименте участвовали несколько программ:
• Cuda - решение, описанное в настоящей статье, использующее возможности СИБЛ
• Сри - решение, использующее только мощности процессора; представляет собой модификацию программы Cuda, в которой значение к понижено до 1, а код работы с СИБЛ исключен за ненадобностью.
• ЬР - решение на основе методов линейного программирования для оценки ответа снизу [3].
• Gene - генетическое решение для оценки ответа сверху.
Тесты сгенерированы случайным образом. Каждая из величин задается случайным образом на соответствующих отрезках: W є [30,100],
W є [1,W/2], bt є [1,W/3].
Вычисления проводились на машине Core i7, 8Gb RAM, GeForce GTX 5б0. Результаты вычислительного эксперимента представлены в табл.
Таблица
Результаты вычислительного эксперимента
Тест n Время Cpu Время CUDA T(s) LP T(s) exact T(s) gene
B1 10 0.2 с 0.4 с 70 72 72
B2 12 0.9 с 0.1 с 13 14 14
B3 13 3.5 с 0.3 с 15 1б 1б
B4 14 12.5 с 1 с 10 10 10
B5 15 б мин 25 с 48 50 51
B6 15 1б ч 1.3 ч 131 132 133
B7 1б 58 мин 4 мин 20 21 21
B8 17 11 ч 1 ч 52 53 54
Анализ времени выполнения говорит о том, что программа Cuda в среднем работает в 12 раз быстрее программы Cpu.
Выводы
Представленный в статье параллельный алгоритм хорошо адаптируется к архитектуре CUDA. Достигнуто 12-кратное уменьшение времени работы по сравнению с аналогичным решением, не использующим возможности CUDA.
Полученные результаты показывают перспективность параллельного подхода в отношении решения задачи 1CBPP.
Работа поддержана грантом РФФИ № 12-07-00631-а.
ЛИТЕРАТУРА
1. Martello S., Monachi M., Vigo D. An exact approach to the strip-packing problem // INFORMS Journal on Computing. 2003. №15(3). P. 310-319.
2. Месягутов М. А. Задача двумерной ортогональной упаковки: поиск нижней границы на базе решения одномерной продолженной упаковки // Информационные технологии. 2010. №6. С. 13-23.
3. Картак В. М., Месягутов М. А., Мухачева Э. А., Филиппова А. С. Локальный поиск ортогональных упаковок с использованием нижних границ // Автоматика и телемеханика. 2009. №6. С. 167-180.
4. Месягутов М. А. Методы принятия оптимальных решений на основе анализа эффективности значений функции цели в задачах прямоугольной упаковки: Автореф. дис. канд. физ.-мат. наук. Уфа, 2010. 19 с.
5. Hartmarm S. Project Scheduling under limited resources. Models, methods and applications. Berlin: Springer, 1999.
6. Мухачева Э. А., Мухачева А. С. Задача прямоугольной упаковки: методы локального поиска оптимума на базе блочных структур // Автоматика и телемеханика. 2004. №2. С. 10-15.
Поступила в редакцию 09.12.2012 г.