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

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

Несмотря на то, что вы создаете только одну задачу для связывающегося задания, система копирует эту задачу для каждого рабочего, который запускает задание. Например, если связывающееся задание работает на четырех рабочих, 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 функция.