2016-10-25 4 views
1

Рассмотрим следующую пару функций:Как печатать в тот же файл из разных Итераций 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, и вы получите сообщение об ошибке:

Error using fileMid (line 2)
Invalid file identifier. Use fopen to generate a valid file identifier.

Есть ли способ решить эту проблему?

BTW, мне не нужен порядок, в котором итерации печатаются.

ответ

0

Проблема в коде выше, что после первого доступа к файлу я пытаюсь передать это 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" 
1

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

Лучшей идеей было бы, чтобы каждый рабочий выводил свой собственный уникальный файл, например имя файла, а также уникальный идентификатор для рабочего. Этот идентификатор может быть получен из labindex при использовании spmd:

[filePath, fileName, fileExt] = fileparts(file_name); 
workerFile = fullfile(filePath, [file_name '_' int2str(labindex) fileExt]); 

или из current task object при использовании parfor:

[filePath, fileName, fileExt] = fileparts(file_name); 
task = getCurrentTask; 
workerFile = fullfile(filePath, [file_name '_' int2str(task.ID) fileExt]); 

Затем, когда рабочие закончили, есть мастер-процесс сбора отдельных файлов данных в один файл.