Дальнейшие примечания по связывающимся заданиям

Количество задач в связывающемся задании

Несмотря на то, что вы создаете только одну задачу для связывающегося задания, система копирует эту задачу для каждого рабочего, который запускает задание. Например, если связывающееся задание работает на четырех рабочих, свойство Tasks задания содержит четыре объекта задачи. Первая задача в свойстве Tasks задания соответствует задаче, запущенной рабочим, labindex которого является 1, и так далее, так, чтобы свойство ID для объекта задачи и labindex для рабочего, который запустил ту задачу, имели то же значение. Поэтому последовательность результатов, возвращенных функцией fetchOutputs, соответствует значению labindex и к порядку задач в свойстве Tasks задания.

Избегайте мертвой блокировки и других ошибок зависимости

Поскольку код, запускающийся в одном рабочем для связывающегося задания, может блокировать выполнение, пока некоторый соответствующий код не выполняется на другом рабочем, потенциал для мертвой блокировки существует в связывающихся заданиях. Это, скорее всего, произойдет при передаче данных между рабочими или при создании кодозависимым на labindex в операторе if. Некоторые примеры иллюстрируют распространенные ошибки.

Предположим, что у вас есть codistributed массив D, и вы хотите использовать функцию gather, чтобы собрать целый массив в рабочей области одного рабочего.

if labindex == 1
    assembled = gather(D);
end

Причина, которую это приводит к сбою, состоит в том, потому что функция gather требует связи между всеми рабочими, на которых распределяется массив. Когда оператор if ограничивает выполнение одним рабочим, другие рабочие, требуемые для выполнения функции, не выполняют оператор. Как альтернатива, можно использовать сам gather, чтобы собрать данные в рабочую область одного рабочего: assembled = gather(D, 1).

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

from_lab_left = mod(labindex - 2, numlabs) + 1;
to_lab_right  = mod(labindex, numlabs) + 1;

Затем попытайтесь передать данные вокруг звонка.

labSend (outdata, to_lab_right);
indata = labReceive(from_lab_left);

Причина, которую может привести к сбою этот код, состоит в том, потому что, в зависимости от размера передаваемых данных, функция labSend может блокировать выполнение в рабочем, пока соответствующий рабочий получения не выполняет его функцию labReceive. В этом случае все рабочие пытаются отправить одновременно, и ни один не пытается получить, в то время как labSend блокировали их. Другими словами, ни один из рабочих не добирается до их операторов labReceive, потому что они все блокируются в операторе labSend. Чтобы избежать этой конкретной проблемы, можно использовать функцию labSendReceive.