c#多线程快速处理大量数据

c#多线程快速处理大量数据,c#,multithreading,text,C#,Multithreading,Text,嘿,我在一个文本文件中有+15000000条记录 我需要处理每一行 是否使用多线程将非常有用 有什么建议吗? 例如,创建10000个线程并除以15000000/10000,给每个线程提供少量数据?您可以使用并行Linq(PLinq): 您可以轻松地将并行版本与顺序版本进行比较:注释掉.aspallel()和。使用degreeofparallelism(10)或添加。AsSequential()您可以使用并行Linq(PLinq): 您可以轻松地将并行版本与顺序版本进行比较:要么注释掉.aspal

嘿,我在一个文本文件中有+15000000条记录 我需要处理每一行 是否使用多线程将非常有用 有什么建议吗? 例如,创建10000个线程并除以15000000/10000,给每个线程提供少量数据?

您可以使用并行Linq(PLinq):

您可以轻松地将并行版本与顺序版本进行比较:注释掉
.aspallel()
。使用degreeofparallelism(10)
或添加
。AsSequential()

您可以使用并行Linq(PLinq):


您可以轻松地将并行版本与顺序版本进行比较:要么注释掉
.aspallel()
。使用degreeofparallelism(10)
,要么添加
。AsSequential()

您需要一个线程安全的集合和并行循环。假设您将所有行读取到线程安全列表中,您可以这样使用它:

所需名称空间:

using System.Collections.Concurrent;
using System.Threading.Tasks;
代码:

ConcurrentBag items=新的ConcurrentBag(File.ReadLines(@“C:\input.txt”);
ParallelOptions po=new ParallelOptions(){MaxDegreeOfParallelism=10};
Parallel.ForEach(项目、采购订单、行=>
{
流程项目(行);
});

您需要线程安全的集合和并行循环。假设您将所有行读取到线程安全列表中,您可以这样使用它:

所需名称空间:

using System.Collections.Concurrent;
using System.Threading.Tasks;
代码:

ConcurrentBag items=新的ConcurrentBag(File.ReadLines(@“C:\input.txt”);
ParallelOptions po=new ParallelOptions(){MaxDegreeOfParallelism=10};
Parallel.ForEach(项目、采购订单、行=>
{
流程项目(行);
});

这实际上取决于行处理功能。 例如,我生成的文件有5000000行。然后我创建了3个函数:

void Seq()
{
    foreach (var line in File.ReadLines(fname))
    {
        Process(line);
    }
}

void Parallel1()
{
    Parallel.ForEach(File.ReadLines(fname), line=>Process(line));
}

void Parallel2()
{
    var list = new List<string>();
    var tasks = new List<Task>();

    foreach (var line in File.ReadLines(fname))
    {
        list.Add(line);
        if (list.Count > 1000)
        {
            var local = list;
            list = new List<string>();
            tasks.Add(Task.Run(()=>local.ForEach(x=>Process(x))));
        }
    }

    tasks.Add(Task.Run(()=>list.ForEach(x=>Process(x))));

    Task.WaitAll(tasks.ToArray());
}
我的处理功能非常快:

private void Process (string line)
{   
    for (var i = 0; i < 20; i++)
    {
    }
}
私有作废流程(字符串行)
{   
对于(变量i=0;i<20;i++)
{
}
}
我得到的结果是:

Seq 00:00:00.9817211
Parallel1 00:00:01.0199068
Parallel2 00:00:00.6581931 <- fastest
Seq 00:00:00.9817211
平行线1 00:00:01.0199068

Parallel2 00:00:00.6581931这实际上取决于行处理功能。 例如,我生成的文件有5000000行。然后我创建了3个函数:

void Seq()
{
    foreach (var line in File.ReadLines(fname))
    {
        Process(line);
    }
}

void Parallel1()
{
    Parallel.ForEach(File.ReadLines(fname), line=>Process(line));
}

void Parallel2()
{
    var list = new List<string>();
    var tasks = new List<Task>();

    foreach (var line in File.ReadLines(fname))
    {
        list.Add(line);
        if (list.Count > 1000)
        {
            var local = list;
            list = new List<string>();
            tasks.Add(Task.Run(()=>local.ForEach(x=>Process(x))));
        }
    }

    tasks.Add(Task.Run(()=>list.ForEach(x=>Process(x))));

    Task.WaitAll(tasks.ToArray());
}
我的处理功能非常快:

private void Process (string line)
{   
    for (var i = 0; i < 20; i++)
    {
    }
}
私有作废流程(字符串行)
{   
对于(变量i=0;i<20;i++)
{
}
}
我得到的结果是:

Seq 00:00:00.9817211
Parallel1 00:00:01.0199068
Parallel2 00:00:00.6581931 <- fastest
Seq 00:00:00.9817211
平行线1 00:00:01.0199068


Parallel2 00:00:00.6581931为什么不试试看——多线程是否有好处?无论如何,除非处理器有1000个内核,否则10000个线程看起来太多了。看看并行Linq(PLinq):
File.ReadLines(@“C:\MyFile.txt”).AsParallel()…
:比较并行(即
AsParallel()
)和顺序(注释
AsParallel()
)版本您可以打开多少线程是有限制的。在这种情况下,我支持PLinq的建议。但是,如果这被证明过于简单,那么请查看TPL(Task Parallel Library,主要是
Task
类),而不是创建您自己的
Thread
对象,因为它会根据需要智能地创建它们并重用它们,等等。不要使用10k线程,这将导致灾难。使用处理器或x2的内核数。为什么不试试看——多线程是否有好处?无论如何,除非处理器有1000个内核,否则10000个线程看起来太多了。看看并行Linq(PLinq):
File.ReadLines(@“C:\MyFile.txt”).AsParallel()…
:比较并行(即
AsParallel()
)和顺序(注释
AsParallel()
)版本您可以打开多少线程是有限制的。在这种情况下,我支持PLinq的建议。但是,如果这被证明过于简单,那么请查看TPL(Task Parallel Library,主要是
Task
类),而不是创建您自己的
Thread
对象,因为它会根据需要智能地创建它们并重用它们,等等。不要使用10k线程,这将导致灾难。使用处理器或x2的内核数。是否建议在开始处理之前读取所有数据?是否建议在开始处理之前读取所有数据?是否建议加快文件读取速度?@tym32167:通常,文件读取速度是一个限制因素(尤其是当文件存储在HDD上时)。我们可以尝试分离文件读取和文件处理(当下一个文件的块正在读取时,我们可以很好地处理前面的一些行)。在最好的情况下,读取和处理文件所需的时间等于读取文件所需的时间。这不是您在这里尝试的。根据您的代码,您正在尝试并行读取文件中的每一行(我不确定这一顺序是否安全或更快)。然后,您希望分别处理每一行。它增加了多少上下文开关?但你们不知道,流程1生产线要花多少时间。从我的观点来看,如果进程1行非常快,那么应该只有两个线程,一个用于读取文件,一个用于处理。@tym32167:
file.ReadLines
在读取行时使用缓冲区(例如,它读取8k文件数据,然后将其拆分为,比如说,现在在内存缓冲区中的20行)。最佳并行度(
2
10
Environment.ProcessorCount
)是一个可讨论的问题,因为我们不知道(您说得很对!)单行所需的时间。这就是我推荐PLinq的原因问:学位很容易指定。我不知道缓冲区的事实如何影响对File.ReadLines的并发访问。我在MSDN中没有找到任何关于并发访问File.ReadLined的信息。但我们仍然不认为在不了解ProcessLine(…)函数的情况下,我们可以向用户建议任何东西,因为在ProcessLine比读取快得多的情况下,使用多线程是毫无意义的。如果这个进程线速度很慢,那么将这个进程线更改为能够一次处理一大块行是有意义的
private void Process (string line)
{   
    for (var i = 0; i < 200; i++)
    {
    }
}

Seq 00:00:04.3995186
Parallel1 00:00:01.4569537 <- fastest
Parallel2 00:00:02.0348749