C#-多处理(来自python)

C#-多处理(来自python),c#,multiprocessing,C#,Multiprocessing,我有一个python脚本,我想用C#重写它,它利用了多处理。我一直在读关于C#多线程和多处理的书,我完全搞糊涂了。许多文章建议使用TPL或类似Parralel.Foreach的东西,但许多页面从提到多核开始,然后快速切换到讨论线程。在Python中,我必须专门使用多处理模块来实现这一点(请参见:) 我编写了一个小样本控制台应用程序来测试: class Program { static void Main(string[] args) {

我有一个python脚本,我想用C#重写它,它利用了多处理。我一直在读关于C#多线程和多处理的书,我完全搞糊涂了。许多文章建议使用TPL或类似Parralel.Foreach的东西,但许多页面从提到多核开始,然后快速切换到讨论线程。在Python中,我必须专门使用多处理模块来实现这一点(请参见:)

我编写了一个小样本控制台应用程序来测试:

class Program
    {
        static void Main(string[] args)
        {
            List<int> testList = new List<int>();
            testList.AddRange(Enumerable.Range(1, 20));

            Parallel.ForEach(testList, x => Console.WriteLine(Test(x)));

            Console.ReadLine();
        }

        private static string Test(int i)
        {
            Thread.Sleep(1000 * (21 - i));
            return "P: " + Process.GetCurrentProcess().Id.ToString() + ", T: " + Thread.CurrentThread.ManagedThreadId.ToString();
        }
    }
类程序
{
静态void Main(字符串[]参数)
{
List testList=新列表();
AddRange(Enumerable.Range(1,20));
Parallel.ForEach(testList,x=>Console.WriteLine(Test(x));
Console.ReadLine();
}
专用静态字符串测试(int i)
{
睡眠(1000*(21-i));
返回“P:+Process.GetCurrentProcess().Id.ToString()+”,T:+Thread.CurrentThread.ManagedThreadId.ToString();
}
}
但是,它显示一个进程ID和多个线程ID。现在我不确定我的方法是否正确,我是否正确地理解了所有事情

为了提供一点背景知识,我的应用程序需要在少量数据集(+-300个数据点)上进行大量计算,但由于参数组合庞大,我需要这些参数以尽可能快的速度运行以节省时间


基本上,我想知道的是Parallel.Foreach线程是否会自动在不同的内核上运行,或者我是否需要执行其他操作。

Microsoft.NET运行时将.NET线程映射到Windows线程1:1(因此每个.NET线程都是Windows OS线程)。Windows调度程序通常将不同的Windows线程调度到不同的CPU内核。所以你什么都不用做


始终记住,线程是“昂贵”的对象。除非您可以为每个线程进行“大量”工作,否则使用它们是没有用的(不要将线程用于<1秒的工作单元,除非您有非常特殊的需要)

Microsoft.NET运行时将.NET线程映射到Windows线程1:1(因此每个.NET线程都是Windows OS线程)。Windows调度程序通常将不同的Windows线程调度到不同的CPU内核。所以你不必做任何事情。
Parallel.ForEach
将创建
任务
s,这是对工作的逻辑抽象。这些部分将被安排在线程池之上运行,线程池操作
thread
对象,这些对象将在一个系统进程内使用系统线程来完成作业。线程将由操作系统调度,并且可能会在不同的内核上运行(不是100%,因为您不能直接操纵调度,但它们很可能会)。因此,它的工作方式是:ForEach->Tasks->Scheduling in thread pool->.net Threads->OS Threads->OS Scheduling->CPU core拥有多个线程调用
控制台。控制台输出是同步的,以便可以从多个线程调用它,但不会更快。每当多个线程调用Console.WriteLine时,一次只能有一个线程执行任何操作。其余的将被阻止,等待。谢谢,控制台只是为了测试。我不会在实际的程序中使用它。实际的程序将遍历我的数据点,并根据参数组合进行计算,然后返回一个数据对象,该对象给出我的结果,我计划将其存储在列表中,并在列表上进行过滤。你确定第一句话吗?我可以发誓,CLR做的恰恰相反,它没有将托管线程直接绑定到本机/OS线程,这就是为什么它可以根据需要将托管线程从一个本机线程切换到另一个本机线程的原因。也许这在较新版本的CLR中有所改变?@CodyGray一开始,Microsoft不想将.NET线程绑定到操作系统线程,以便能够在SQL.NET运行时使用Windows光纤(光纤类似于协程),但后来他们发现了许多问题,因此即使是SQL.NET运行时也不使用光纤。我似乎同意你的看法@CodyGray@DavidG是的,但请注意给出的示例:具体来说,一个复杂的主机可以使用Fibre API针对同一个操作系统线程调度多个托管线程,或者在不同的操作系统线程之间移动托管线程。。。没有这样的主人。所以这只是一个理论上的练习。例如,在SQL server::Common language runtime(CLR)页面中,轻量级池不支持执行(轻量级池是光纤的使用),Mmmh发现文章::CLR尝试在Whidbey中添加对光纤的支持。这是为了响应SQL Server Yukon托管的运行时进程,也称为SQLCLR。最后,主要是由于日程安排的压力和与光纤模式相关的长应力bug尾巴,我们举手宣布它不受支持