Сортировка массива объектов в PHP в определенном порядке

Использование multiprocessing требует отправки рабочим процессам информации о выполняемой функции, а не только аргументы для передачи. Эта информация передается травлением , что информация в основном процессе, отправка его в рабочий процесс и ее рассыпание.

Это приводит к основной проблеме:

Травление функции с аргументами по умолчанию дешево; он только замачивает имя функции (плюс информация, чтобы Python знал, что это функция); рабочие процессы просто ищут локальную копию имени. У них уже есть именованная функция f, чтобы найти ее, поэтому ей почти ничего не стоит.

Но травление функции partial включает в себя травление основной функции (дешево) и всех аргументы по умолчанию ( дорогие , когда аргумент по умолчанию - 10M list). Поэтому каждый раз, когда задача отправляется в случае partial, она травит связанный аргумент, отправляет его в рабочий процесс, рабочий процесс распаковывается, а затем выполняет «настоящую» работу. На моей машине этот рассол имеет размер примерно 50 МБ, что является огромным объемом накладных расходов; в быстрых тестах времени на моей машине, травление и рассыпание 10 миллионов длинной list из 0 занимает около 620 мс (и это игнорирует накладные расходы на фактическую передачу 50 МБ данных).

partial должны рассосаться таким образом, потому что они не знают своих имен; при расчете функции, подобной f, f (будучи def -ed) знает свое квалифицированное имя (в интерактивном интерпретаторе или из основного модуля программы это __main__.f), поэтому удаленная сторона может просто воссоздайте его локально, выполнив эквивалент from __main__ import f. Но partial не знает его имени; конечно, вы назначили его g, но ни pickle, ни partial сами не знают, что это доступно с квалифицированным именем __main__.g; его можно было бы назвать foo.fred или миллион других вещей. Поэтому он должен pickle получить информацию, необходимую для воссоздания целиком с нуля. Это также pickle для каждого вызова (не один раз на одного рабочего), потому что он не знает, что вызываемый не меняет родителя между рабочими элементами, и он всегда пытается обеспечить его отправку в актуальное состояние.

У вас есть другие проблемы (создание временного времени для list только в случае partial и незначительные накладные расходы при вызове функции partial, завершенной или вызывающей функцию напрямую), но это chump изменение относительно накладного травления для каждого вызова и разблокировка partial добавляется (первоначальное создание list добавляет одноразовые служебные данные чуть ниже половины того, что каждый цикл pickle / unpickle расходы, накладные расходы для вызова через partial меньше, чем микросекунда).

14
задан Paul Dixon 10 December 2008 в 11:04
поделиться

2 ответа

Используйте usort и обеспечьте пользовательскую функцию сравнения, которая использует положение ключа в Вашем массиве "упорядочивания" для определения порядка сортировки, например, чего-то как:

function cmp($a, $b) 
{
   global $author_array;

   $pos1=array_search ($a->ID, $author_array);
   $pos2=array_search ($b->ID, $author_array);

   if ($pos1==$pos2)
       return 0;
   else
      return ($pos1 < $pos2 ? -1 : 1);

}


usort($user_results, "cmp");
29
ответ дан 1 December 2019 в 08:20
поделиться

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

$hash = array();
$result = array();

foreach ($user_results as $obj) {
    $hash[$obj->ID] = $obj;
}

foreach ($author_array as $id) {
    $result[] = $hash[$id];
}
3
ответ дан 1 December 2019 в 08:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: