如何验证n个方法是否并行执行?
How to verify that n methods are executing in parallel?
仅供参考,如何验证 n 个方法是否并行执行?
Parallel.For(0, 10, i => DoSomething(i));
...
void DoSomething(int par)
{
Console.WriteLine($"Test: {par}");
}
是否有测试可以确保 DoSomething 不会按顺序执行(如果 Console.WriteLine
不是一个好的测试,那么什么是非常简单的测试函数?)
在您的示例中,方法肯定是顺序的,因为 .NET 控制台将 synchronize calls from different threads。
但是,您可以使用 Thread.ManagedThreadID or Environment.CurrentManagedThreadId(对于 .NET 4.5)
检查正在 运行 方法的线程 ID
class Program
{
static void Main(string[] args)
{
// first run with default number of threads
Parallel.For(0, 10, i => DoSomething(i));
Console.ReadLine();
// now run with fewer threads...
Parallel.For(0, 10, new ParallelOptions{
MaxDegreeOfParallelism = 2
}, i => DoSomething(i));
Console.ReadLine();
}
static void DoSomething(int par)
{
int i = Environment.CurrentManagedThreadId;
// int i = Thread.ManagedThreadId; -- .NET 4.0 and under
Thread.Sleep(200);
Console.WriteLine("Test: "+ par.ToString() +
", Thread :" + i.ToString());
}
}
如果你 运行 没有 Thread.Sleep
你会注意到只有几个线程将被使用,因为调用将足够快地完成,以便线程及时返回到池中拿起队列分配的下一个作业。
添加睡眠将使线程(模拟工作)延迟足够长的时间,以至于线程池将不得不获取更多线程以及时将作业分拆出来。
当 运行 并行执行任何任务时,很容易检查这些任务实际上是否都 运行 在单独的线程中执行。然而,您是否获得性能优势将取决于这些线程的工作效率。如您所见,某些操作会引起对共享资源的争用(例如写入控制台),并且会阻止您的多个线程同时运行。
争用的其他来源可能是,例如,内存分配 - 如果您的线程都在大量分配和取消分配内存,那么它们最终可能会花费大量时间等待轮到内存管理器。这将限制您将实现的实际并行度。
不确定我是否理解你想要做什么。你可以数一数。
Parallel.For(0, 10, i => DoSomething(i));
...
private static int parallelCounter = 0;
private static object counterLockObject = new Object();
void DoSomething(int par)
{
int myCounter;
lock(counterLockObject)
{
myCounter = ++parallelCounter;
}
try
{
// you probably need something that takes more time to
// see anything executing in parallel
Console.WriteLine("Current number of parallel threads: {0}", myCounter);
}
finally
{
lock(counterLockObject)
{
parallelCounter--;
}
}
}
您可以使用以下代码检查并行执行了多少方法:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ParallelMethodsCounter
{
class Program
{
public static int _parallelCounter = 0;
public static int _maxParallelExecutionsCount = 0;
static void Main(string[] args)
{
Parallel.For(0, 10, i => DoSomething(i));
Console.WriteLine("MAX PARALLEL EXECUTIONS: {0}", _maxParallelExecutionsCount);
}
public static void DoSomething(int par)
{
int currentParallelExecutionsCount = Interlocked.Increment(ref _parallelCounter);
InterlockedExchangeIfGreaterThan(ref _maxParallelExecutionsCount, currentParallelExecutionsCount, currentParallelExecutionsCount);
Console.WriteLine("Current parallel executions: {0}", currentParallelExecutionsCount);
try
{
//Do your work here
}
finally
{
Interlocked.Decrement(ref _parallelCounter);
}
}
public static bool InterlockedExchangeIfGreaterThan(ref int location, int comparison, int newValue)
{
int initialValue;
do
{
initialValue = location;
if (initialValue >= comparison) return false;
}
while (Interlocked.CompareExchange(ref location, newValue, initialValue) != initialValue);
return true;
}
}
}
但请记住,Parallel.For 不会尝试并行执行太多,因为它使用线程池,并且默认情况下使用的线程数等于您的处理器内核数。在我的四核机器上,我通常有 2-4 个并行执行,有时最多执行 5 个(当然这里没有严格限制)。
仅供参考,如何验证 n 个方法是否并行执行?
Parallel.For(0, 10, i => DoSomething(i));
...
void DoSomething(int par)
{
Console.WriteLine($"Test: {par}");
}
是否有测试可以确保 DoSomething 不会按顺序执行(如果 Console.WriteLine
不是一个好的测试,那么什么是非常简单的测试函数?)
在您的示例中,方法肯定是顺序的,因为 .NET 控制台将 synchronize calls from different threads。
但是,您可以使用 Thread.ManagedThreadID or Environment.CurrentManagedThreadId(对于 .NET 4.5)
检查正在 运行 方法的线程 IDclass Program
{
static void Main(string[] args)
{
// first run with default number of threads
Parallel.For(0, 10, i => DoSomething(i));
Console.ReadLine();
// now run with fewer threads...
Parallel.For(0, 10, new ParallelOptions{
MaxDegreeOfParallelism = 2
}, i => DoSomething(i));
Console.ReadLine();
}
static void DoSomething(int par)
{
int i = Environment.CurrentManagedThreadId;
// int i = Thread.ManagedThreadId; -- .NET 4.0 and under
Thread.Sleep(200);
Console.WriteLine("Test: "+ par.ToString() +
", Thread :" + i.ToString());
}
}
如果你 运行 没有 Thread.Sleep
你会注意到只有几个线程将被使用,因为调用将足够快地完成,以便线程及时返回到池中拿起队列分配的下一个作业。
添加睡眠将使线程(模拟工作)延迟足够长的时间,以至于线程池将不得不获取更多线程以及时将作业分拆出来。
当 运行 并行执行任何任务时,很容易检查这些任务实际上是否都 运行 在单独的线程中执行。然而,您是否获得性能优势将取决于这些线程的工作效率。如您所见,某些操作会引起对共享资源的争用(例如写入控制台),并且会阻止您的多个线程同时运行。
争用的其他来源可能是,例如,内存分配 - 如果您的线程都在大量分配和取消分配内存,那么它们最终可能会花费大量时间等待轮到内存管理器。这将限制您将实现的实际并行度。
不确定我是否理解你想要做什么。你可以数一数。
Parallel.For(0, 10, i => DoSomething(i));
...
private static int parallelCounter = 0;
private static object counterLockObject = new Object();
void DoSomething(int par)
{
int myCounter;
lock(counterLockObject)
{
myCounter = ++parallelCounter;
}
try
{
// you probably need something that takes more time to
// see anything executing in parallel
Console.WriteLine("Current number of parallel threads: {0}", myCounter);
}
finally
{
lock(counterLockObject)
{
parallelCounter--;
}
}
}
您可以使用以下代码检查并行执行了多少方法:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ParallelMethodsCounter
{
class Program
{
public static int _parallelCounter = 0;
public static int _maxParallelExecutionsCount = 0;
static void Main(string[] args)
{
Parallel.For(0, 10, i => DoSomething(i));
Console.WriteLine("MAX PARALLEL EXECUTIONS: {0}", _maxParallelExecutionsCount);
}
public static void DoSomething(int par)
{
int currentParallelExecutionsCount = Interlocked.Increment(ref _parallelCounter);
InterlockedExchangeIfGreaterThan(ref _maxParallelExecutionsCount, currentParallelExecutionsCount, currentParallelExecutionsCount);
Console.WriteLine("Current parallel executions: {0}", currentParallelExecutionsCount);
try
{
//Do your work here
}
finally
{
Interlocked.Decrement(ref _parallelCounter);
}
}
public static bool InterlockedExchangeIfGreaterThan(ref int location, int comparison, int newValue)
{
int initialValue;
do
{
initialValue = location;
if (initialValue >= comparison) return false;
}
while (Interlocked.CompareExchange(ref location, newValue, initialValue) != initialValue);
return true;
}
}
}
但请记住,Parallel.For 不会尝试并行执行太多,因为它使用线程池,并且默认情况下使用的线程数等于您的处理器内核数。在我的四核机器上,我通常有 2-4 个并行执行,有时最多执行 5 个(当然这里没有严格限制)。