考虑以下一对功能:
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生成有效的文件标识符。
有没有办法解决这个问题?
顺便说一下,我并不关心迭代的打印顺序。答案 0 :(得分:2)
让多个进程修改同一资源通常是不明智的。如果两个进程碰巧在同一时间写入文件,最终可能会使输出交错或相互覆盖。
更好的想法是让每个worker输出到它自己的唯一文件,例如文件名加上一些工作者唯一的标识符。使用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]);
然后,一旦工人完成,让主进程将各个数据文件收集到一个文件中。
答案 1 :(得分:0)
上面代码中的问题是,在第一次访问文件后,我试图将它fid
传递给工作者,但是它们无法与主程序连接,因此他们发现<{1}}无法访问的文件。
解决这个问题的方法,虽然我不确定是否推荐,但是将文件名本身传递给worker,并在每个worker中打开和关闭该文件。这是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