2011-01-15 2 views
16

У меня проблема, когда я должен проанализировать комбинации 500C5 (255244687600) чего-то. Распространение его на кластер из 10 узлов, где каждый кластер обрабатывает примерно 10^6 комбинаций в секунду, означает, что работа будет завершена примерно через семь часов.Перечисление комбинаций распределенным образом

Проблема заключается в распределении комбинаций 255244687600 по 10 узлам. Я хотел бы представить каждый узел 25524468760, однако алгоритмы, которые я использую, могут производить только комбинации последовательно, я хотел бы иметь возможность передавать набор элементов и диапазон комбинаций, например, [0 -10^7), [10^7,2,0 10^7] и т. Д., И сами узлы вычисляют комбинации.

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

Я рассмотрел с использованием ведущий узел, который перечисляет каждую из комбинаций и отправляет работу каждому из них треб. Однако накладные расходы, возникающие при итерации комбинаций из одного узла и передачи назад и вперед работы, огромны, и это впоследствии приведет к тому, что главный узел станет узким местом.

Есть ли хорошие алгоритмы итерации комбинации, предназначенные для эффективного/оптимального распределенного перечисления?

+0

Не так много опыта в этой области, но это звучит как проблема, которая может быть Google MapReduce применительно к. –

+7

MapReduce здесь не имеет значения, так как речь идет о части «Карта» термина: Как эффективно отображать проблему пространства n-select-k в m частей без необходимости для центрального дистрибьютора. –

+0

@Reyzooti: Отсюда «не много опыта». Счастлив исправить. –

ответ

3

Вы можете иметь некоторый успех с combinatorial numbers, которые позволяют получить тый N»(п/10) K -combination с простым алгоритмом; затем выполните алгоритм next_combinationn/10 раз на каждом из десяти узлов для повторения.

Пример кода (в C#, но вполне читаемый для программиста на C++) можно найти на MSDN.

+0

Статья Джеймса МакКаффри, где он описывает метод получения N-й комбинации, слишком дорога. Использование next_combination (ссылки) изменяет исходный диапазон, возможно, что-то, что может определить, как выглядит диапазон в N-й комбинации, потому что можно передать этот конкретный диапазон в вычислительный узел. –

+0

Почему это слишком дорого?Вам нужно всего лишь запустить это 10 раз на master, а затем запустить 'next_combination' на вычислительных узлах. –

+0

@Reyzooti: если у вас есть индексная вещь, то превратить ее в RandomAccessIterator легко -> держать указатель на последовательность и индекс в итераторе :) –

0

Нужно иметь номер узла n для каждой десятой комбинации, начиная с n-го.

+4

По-прежнему требуется, чтобы каждый узел перебирал все комбинации n-select-k, что приводило к 90% -ной итерационной редуальности на узел, меньше накладных расходов, чем решение главного узла, но все же больше, чем распределение диапазонов комбинаций. –

0

Я знаю, что этот вопрос старый, но вот как это можно сделать эффективно.

Весь код в настоящее время в Python, который, я уверен, будет достаточно простым для перевода на C++.
- Вы, вероятно, захотите перейти от использования целого числа для вектор-характеристики к использованию битового массива, поскольку для использования целых чисел потребуется 500 бит (не проблема в Python).
- Не стесняйтесь обновлять никого на C++.


  1. Распределить к узлам их диапазон комбинаций (start количество и length для обработки), набор из items, какие комбинации должны быть выбраны и число, k, элементов на выбор.
  2. Инициализируйте каждый узел, найдя его исходную комбинацию непосредственно с start и items.
  3. Запустите каждый узел, запустив его для первой комбинации, затем повторите все остальные комбинации и выполните соответствующую работу.

Для выполнения сделать как вы предлагаете найти н-выбрать-к и разделить его на диапазоны - в вашем случае 500-Выберите-5, как вы сказали, 255244687600 так, для узла = от 0 до 9 вы распространяете:
(start=node*25524468760, length=25524468760, items=items, k=5)

чтобы выполнить можно найти начальную комбинацию непосредственно (без итерации) с использованием системы комбинаторного числа и найти целочисленное представление характеристического вектора комбинации (в который будет использоваться для итерации в) в то же самое время:

def getCombination(index, items, k): 
    '''Returns (combination, characteristicVector) 
    combination - The single combination, of k elements of items, that would be at 
    the provided index if all possible combinations had each been sorted in 
    descending order (as defined by the order of items) and then placed in a 
    sorted list. 
    characteristicVector - an integer with chosen item's bits set. 
    ''' 
    combination = [] 
    characteristicVector = 0 
    n = len(items) 
    nCk = 1 
    for nMinusI, iPlus1 in zip(range(n, n - k, -1), range(1, k + 1)): 
     nCk *= nMinusI 
     nCk //= iPlus1 
    curIndex = nCk 
    for k in range(k, 0, -1): 
     nCk *= k 
     nCk //= n 
     while curIndex - nCk > index: 
      curIndex -= nCk 
      nCk *= (n - k) 
      nCk -= nCk % k 
      n -= 1 
      nCk //= n 
     n -= 1 
     combination .append(items[n]) 
     characteristicVector += 1 << n 
    return combination, characteristicVector 

Целое представление характеристического вектора имеет к битам, установленных в позициях элементов, составляющих комбинацию.

Для выполнения вы можете использовать хак Госпером для итерации к следующей характеристике вектора для комбинации в одной и той же системе счисления (следующую комбинацию, которая будет отображаться в отсортированном списке обратных отсортирован комбинаций относительно items) и, в то же время, создают комбинацию:

def nextCombination(items, characteristicVector): 
    '''Returns the next (combination, characteristicVector). 
    combination - The next combination of items that would appear after the 
    combination defined by the provided characteristic vector if all possible 
    combinations had each been sorted in descending order (as defined by the order 
    of items) and then placed in a sorted list. 
    characteristicVector - an integer with chosen item's bits set. 
    ''' 
    u = characteristicVector & -characteristicVector 
    v = u + characteristicVector 
    if v <= 0: 
     raise OverflowError("Ran out of integers") # <- ready for C++ 
    characteristicVector = v + (((v^characteristicVector) // u) >> 2) 
    combination = [] 
    copiedVector = characteristicVector 
    index = len(items) - 1 
    while copiedVector > 0: 
     present, copiedVector = divmod(copiedVector, 1 << index) 
     if present: 
      combination.append(items[index]) 
     index -= 1 
    return combination, characteristicVector 

Повторите этот length-1 раз (так как вы уже нашли первый непосредственно).


Например:

Пять узлов обработки 7-выбрать-3 буквы:

>>> items = ('A','B','C','D','E','F','G') 
>>> k = 3 
>>> nodes = 5 
>>> n = len(items) 
>>> for nmip1, i in zip(range(n - 1, n - k, -1), range(2, k + 1)): 
...  n = n * nmip1 // i 
... 
>>> for node in range(nodes): 
...  length = n // nodes 
...  start = node * length 
...  print("Node {0} initialised".format(node)) 
...  combination, cv = getCombination(start, items, k) 
...  doWork(combination) 
...  for i in range(length-1): 
...    combination, cv = nextCombination(items, cv) 
...    doWork(combination) 
... 
Node 0 initialised 
Doing work with: C B A 
Doing work with: D B A 
Doing work with: D C A 
Doing work with: D C B 
Doing work with: E B A 
Doing work with: E C A 
Doing work with: E C B 
Node 1 initialised 
Doing work with: E D A 
Doing work with: E D B 
Doing work with: E D C 
Doing work with: F B A 
Doing work with: F C A 
Doing work with: F C B 
Doing work with: F D A 
Node 2 initialised 
Doing work with: F D B 
Doing work with: F D C 
Doing work with: F E A 
Doing work with: F E B 
Doing work with: F E C 
Doing work with: F E D 
Doing work with: G B A 
Node 3 initialised 
Doing work with: G C A 
Doing work with: G C B 
Doing work with: G D A 
Doing work with: G D B 
Doing work with: G D C 
Doing work with: G E A 
Doing work with: G E B 
Node 4 initialised 
Doing work with: G E C 
Doing work with: G E D 
Doing work with: G F A 
Doing work with: G F B 
Doing work with: G F C 
Doing work with: G F D 
Doing work with: G F E 
>>> 
Смежные вопросы