我正在编写基准应用程序,它具有线程数和要作为输入参数执行的操作数。 每个基准测试都创建为具有Execute(int numberOfRepeats)方法的独立类。 numberOfRepeats实际上是每个线程中的重复次数。
我通过以下方式创建基准:
例如,我有32个线程,以及50个持久的基准操作。因此每个线程必须执行 50/32 = 1操作(实际为1.56),这将为所有线程提供32个操作的总数。
我使用简单的"新的Thread()"构造多线程和AutoResetEvent与WaitHandle.WaitAll构造同步执行和测量总时间。
我尝试将 Parallel.For 与 ParallelOptions.MaxDegreeOfParallelism 作为线程数,但它并没有实际运行所有线程的基准测试。由于操作数量 100k ,只有 20个线程在线程池中使用 ParallelOptions.MaxDegreeOfParallelism = 128 。
现在问题。如何在线程之间拆分操作以在我描述的情况下执行确切数量的操作?
谢谢!
答案 0 :(得分:1)
并行调度程序不使用那么多线程,因为它足够聪明,知道何时这样做会降低性能。
来自MSDN:
.NET线程池动态适应不断变化的工作负载 允许并行任务的工作线程数量发生变化 随着时间的推移。在运行时,系统观察是否增加 线程数会改善或降低整体吞吐量并进行调整 相应的工作线程数。
如果您使用这么多线程来执行基准,则应重新考虑您的实施。你会降低你的整体性能,因为线程会在每个周期中与每个周期进行斗争,这是你在尝试做基准时间敏感工作时最不想要的事情。
答案 1 :(得分:1)
我找到了在线程之间拆分任意数量操作的简便方法。 此方法将返回int的数组,其中每个元素表示具有索引i的线程的操作数。
private static int[] splitTasksForThreads(int numberOfThreads, int numberOfTasks)
{
var tasksRepeatArray = new int[numberOfThreads];
var taskPerThread = numberOfTasks / numberOfThreads;
var diff = numberOfTasks - (numberOfThreads * taskPerThread);
if (diff == 0)
{
for (int i = 0; i < numberOfThreads; i++)
tasksRepeatArray[i] = taskPerThread;
}
else if (numberOfThreads > numberOfTasks)
{
for (int i = 0; i < numberOfTasks; i++)
{
tasksRepeatArray[i]++;
}
}
else
{
for (int i = 0; i < tasksRepeatArray.Length; i++)
tasksRepeatArray[i] = taskPerThread;
for (int i = 0; i < diff; i++)
tasksRepeatArray[i]++;
}
return tasksRepeatArray;
}
答案 2 :(得分:0)
这是cmd函数的版本,如果操作超过包括注释的线程数,它将减少线程数量。我对此不承担任何责任。因为我的声誉不够高,所以无法发表评论。
internal static IEnumerable<int> GetActionsPerThreads(int numberOfThreads, int numberOfActions)
{
// We have too many threads for the requested amount of actions
while (numberOfActions < numberOfThreads)
{
numberOfThreads--;
}
int[] actionsPerThread = new int[numberOfThreads];
// Intentional loss of data
int perThread = numberOfActions / numberOfThreads;
int actionRemainder = numberOfActions - (numberOfThreads * perThread);
// No need to split anything. The threads can perform an equal amount of actions
if (actionRemainder == 0)
{
for (int i = 0; i < numberOfThreads; i++)
{
actionsPerThread[i] = perThread;
}
}
// We have more actions than we have threads. Time to reduce our thread count to the amount of actions
else if (numberOfThreads > numberOfActions)
{
for (int i = 0; i < numberOfActions; i++)
{
actionsPerThread[i]++;
}
}
// We have an unequal amount of actions per thread, time to split them
else
{
// All threads perform the calculated amount of actions (rounded down)
for (int i = 0; i < actionsPerThread.Length; i++)
{
actionsPerThread[i] = perThread;
}
// Some tasks will have to do more work
for (int i = 0; i < actionRemainder; i++)
{
actionsPerThread[i]++;
}
}
return actionsPerThread;
}