Как печатать в один и тот же файл с разных итераций PARFOR?
Рассмотрим следующую пару функций:
function fileTop
test = fopen('test.txt','w');
fprintf(test,'In function "fileTop"\r\n');
fileMid(test)
fprintf(test,'Back in function "fileTop"');
fclose(test);
end
а также:
function fileMid(fid)
for k = 1:5
pause(rand)
fprintf(test,'In "fileMid %d" at %f\r\n',k,now);
end
end
Если вы просто бежите fileTop
Вы получаете новый текстовый файл (на первый раз) со следующим содержимым:
In function "fileTop"
In "fileMid 1" at 736847.920072
In "fileMid 2" at 736847.920073
In "fileMid 3" at 736847.920081
In "fileMid 4" at 736847.920087
In "fileMid 5" at 736847.920096
Back in function "fileTop"
что просто отлично!
Теперь попробуйте изменить цикл в fileMid
в parfor
и вы получите ошибку:
Ошибка при использовании fileMid (строка 2)
Неверный идентификатор файла. Используйте fopen для создания правильного идентификатора файла.
Есть ли способ решить это?
Кстати, меня не волнует порядок, в котором печатаются итерации.
2 ответа
Как правило, неразумно иметь несколько процессов, модифицирующих один и тот же ресурс. Если два процесса записывают данные в файл в одно и то же время, вы можете получить чередование их выходных данных или перезапись друг друга.
Лучшей идеей будет вывод каждого рабочего в свой уникальный файл, такой как имя файла и некоторый идентификатор, уникальный для рабочего. Этот идентификатор можно получить от labindex
когда используешь spmd
:
[filePath, fileName, fileExt] = fileparts(file_name);
workerFile = fullfile(filePath, [file_name '_' int2str(labindex) fileExt]);
или из текущего объекта задачи при использовании parfor
:
[filePath, fileName, fileExt] = fileparts(file_name);
task = getCurrentTask;
workerFile = fullfile(filePath, [file_name '_' int2str(task.ID) fileExt]);
Затем, после завершения работы, попросите главный процесс собрать отдельные файлы данных в один файл.
Проблема в коде выше, что после первого доступа к файлу, я пытаюсь передать его fid
рабочим, но они не могут соединиться с основной программой, и поэтому они находят файл с fid
как недоступный.
Чтобы решить эту проблему, хотя я не уверен, рекомендуется ли это, передать работникам само имя файла, а также открыть и закрыть файл в каждом работнике. Вот как fileTop
выглядеть после изменения:
function fileTop
file_name = 'test.txt';
test = fopen(file_name,'w');
fprintf(test,'In function "fileTop"\r\n');
fclose(test);
parfor k = 1:5
fileMid(test,k)
end
test = fopen(file_name,'a');
fprintf(test,'Back in function "fileTop"');
fclose(test);
end
А это fileMid
:
function fileMid(file_name,k)
test = fopen(file_name,'a');
pause(rand)
fprintf(test,'In "fileMid %d" at %f\r\n',k,now);
fclose(test);
end
И возможный вывод будет:
In function "fileTop"
In "fileMid 2" at 736847.917401
In "fileMid 4" at 736847.917404
In "fileMid 3" at 736847.917405
In "fileMid 1" at 736847.917409
In "fileMid 5" at 736847.917410
Back in function "fileTop"