我有这个代码,它从文件中读取所有单词,并为每个唯一单词分配ID并将其添加到Dictionary中。我需要让它并行运行以提高应用程序的效率。我尝试过使用Parallel.ForEach
而不是foreach
但是,使用锁定将新单词和ID添加到字典中并不能提高效率...你们能告诉我这是什么来帮助我吗?我可以将此代码并行化的最佳方法?
//static object locker = new object();
string[] fnames; // Files are collected from a save file dialog
Dictionary<string, IndexEntry> ID = new Dictionary<string, IndexEntry>();
foreach (var fname in fnames)
{
string[] lines = File.ReadAllLines(fname);
for (int i = 0; i < lines.Length; i++)
{
string[] Raw = Regex.Split(lines[i], @"\W+");
for (int j = 0; j < Raw.Length; j++)
{
string z = Raw[j];
if (!ID.ContainsKey(z))
{
ID.Add(z, new IndexEntry());
}
}
答案 0 :(得分:0)
如果多个线程访问此代码块,则首先考虑并发字典,这是一个线程安全的。这将为您实现锁定。
编辑:
http://msdn.microsoft.com/en-us/library/dd287191%28v=vs.110%29.aspx
答案 1 :(得分:0)
制作人/消费者模式是你的朋友。
你可以让一个线程读取文件,第二个线程插入到字典中,并且可能有第三个线程执行任何处理需要。第三个线程仅适用于在开始处理之前不必完全填充字典的情况(例如,如果足以读取给定的行)。
请注意,如果处理步骤微不足道,那么与单线程解决方案相比,您的收益将会降到最低。
查看Task Parallel Library。这非常适合这种类型的处理。
我使用这种模式来读取,处理和写入(到数据库)相当大的(1GB +)XML文档。
答案 2 :(得分:0)
问题是你最大的时间消费者正在阅读文件:
string[] lines = File.ReadAllLines(fname);
你一下子就把它啜饮了。你可能每个文件都有一个帖子,但我不认为他们会购买你很多,因为他们的I / O都争用同一个磁盘。尝试用更小的碎片做。这样的事可能对你有用:
static Dictionary<string,IndexEntry> ProcessFiles( IEnumerable<string> filenames )
{
IEnumerable<string> words = filenames
.AsParallel()
//.WithMergeOptions( ParallelMergeOptions.NotBuffered )
.Select( x => ReadWordsFromFile(x) )
.SelectMany( x => x )
;
Dictionary<string,IndexEntry> index = new Dictionary<string,IndexEntry>() ;
foreach( string word in words ) // would making this parallel speed things up? dunno.
{
bool found = index.ContainsKey(word) ;
if ( !found )
{
index.Add( word, new IndexEntry() ) ;
}
}
return index ;
}
static Regex rxWord = new Regex( @"\w+" ) ;
private static IEnumerable<string> ReadWordsFromFile( string fn )
{
using( StreamReader sr = File.OpenText( fn ) )
{
string line ;
while ( (line=sr.ReadLine()) != null )
{
for ( Match m = rxWord.Match(line) ; m.Success ; m = m.NextMatch() )
{
yield return m.Value ;
}
}
}
}