多节点并行写入NFS存储文件的异常问题排查求助
更新内容
我让每个节点写入单独文件,合并后结果正确。我还修改了代码,尝试在每条记录写入后执行通道刷新和文件同步,但目前节点0和1之间仍存在问题:若让节点0在coforall循环迭代前休眠几秒,记录就能正常生成;否则节点0记录的最后几百字节会被可靠地覆盖为NULL字节,直至节点1记录的起始位置。节点1与2、节点2与3之间的问题似乎不再出现。
此外,若抑制节点0或1写入,未被抑制节点的完整记录会被正确写入文件:抑制节点1时,文件中会出现9997条100B的正确记录(共999700字节),后续为节点1被抑制记录对应的NULL字节;抑制节点0时,文件开头为999700字节的NULL,之后是节点1的正常记录。
原帖内容
我正在排查多节点向NFS挂载的共享磁盘文件并行写入时的异常问题,目前怀疑NFS服务器的磁盘写入方式存在问题。
我正在适配原MPI+C中使用pwrite向文件协调块写入的逻辑到Chapel:当通过coforall循环让各对应Locale写入文件时,文件中节点边界附近的数据会出现错乱——通常是每个节点数据的最后几百字节损坏;但仅让一个Locale遍历所有节点的数据并执行写入时,数据完全正确(即使用相同的数据结构计算偏移,仅由Locale 0定位偏移并执行写入)。
我已验证各Locale的写入偏移无重叠,且每个任务使用独立的通道(在on loc do块内定义),避免任务共享单个通道。
不同Locale写入文件是否存在已知问题?多数文档显示该操作是安全的,但我猜测可能存在文件内容缓存问题——检查错误数据时,发现错误部分多为程序启动时对应位置的原始文件数据。
以下是相关例程,供快速排查是否存在遗漏。若要改为串行模式,我会将coforall loc in Locales和on loc do块改为for j in 0..numLocales-1循环,并用j替换here.id。请告知还需提供哪些信息以彻底解决问题,谢谢!
proc write_share_of_data(data_filename: string, ref record_blocks) throws { coforall loc in Locales { on loc do { var data_file: file = open(data_filename, iomode.cwr); var data_writer = data_file.writer(kind=ionative, locking=false); var line: [1..100] uint(8); const indices = record_blocks[here.id].D; var local_record_offset = + reduce record_blocks[0..here.id-1].D.size; writeln("Loc ", here.id, ": record offset is ", local_record_offset); var local_bytes_offset = terarec.terarec_width_disk * local_record_offset; data_writer.seek(start=local_bytes_offset); for i in indices { var write_rec: terarec_t = record_blocks[here.id].records[i]; line[1..10] = write_rec.key; line[11..98] = write_rec.value; line[99] = 13; // 回车 line[100] = 10; // 换行 data_writer.write(line); lines_written += 1; } data_file.fsync(); data_writer.close(); data_file.close(); } } return; }
内容的提问来源于stack exchange,提问作者rws

