当前位置: 代码迷 >> java >> 我的并行运行计时器无法确定问题
  详细解决方案

我的并行运行计时器无法确定问题

热度:76   发布时间:2023-07-26 14:11:42.0

我有一个程序,将中值过滤器应用于超过200万个值的数组。

我正在尝试比较同一数据集上顺序运行与并行运行的时间。 因此,当我执行该程序时,它会执行20次运行,每次运行都会计时,并且平均会向控制台输出20次。

ArrayList<Double> times = new ArrayList<>(20);//to calculate average run time

for (int run = 1; run < 21; run++) //algorithm will run 20 times
{
    long startTime = System.nanoTime();

    switch (method)
    {
        case 1: //Sequential
            filt.seqFilter();
            break;
        case 2: //ForkJoin Framework
            pool.invoke(filt); //pool is ForkJoin
            break;
    }
    Double timeElapsed = (System.nanoTime() - startTime) / 1000000.0;
    times.add(run - 1, timeElapsed);
    System.out.println("Run " + run + ": " + timeElapsed + " milliseconds.");
}

times.remove(Collections.max(times)); //there's always a slow outlier
double timesSum = 0;
for (Double e : times)
{
    timesSum += e;
}
double average = timesSum / 19;
System.out.println("Runtime: " + average);

filtFilterObject类型,它扩展了RecursiveAction 我在FilterObject重写的compute()方法如下所示:

public void compute()
{
    if (hi - lo <= SEQUENTIAL_THRESHOLD)
    {
        seqFilter();
    }
    else
    {
        FilterObject left = new FilterObject(lo, (hi + lo) / 2);
        FilterObject right = new FilterObject((hi + lo) / 2, hi);
        left.fork();
        right.compute();
        left.join(); 
    }
}

seqFilter()处理起始数组中lohi索引之间的值,并将处理后的值添加到相同位置的最终数组中。 这就是在left.join()之后不合并数组的原因。

我的并行运行时间非常快-如此之快,以至于我认为计时器或left.join()语句一定有问题。 连续的平均时间约为170毫秒,而过滤窗口的大小为3,并行的平均为0.004毫秒。 为什么我得到这些值? 我特别担心我的join()放在错误的位置。

如果您想查看我的完整代码,包括所有类和一些输入文件,请 。

对您的代码进行一些测试后,我找到了原因。 事实证明,ForkJoinPool仅运行一个任务实例一次。 具有相同任务实例的后续invoke()调用将立即返回。 因此,您必须在每次运行时重新实例化该任务。

另一个问题是并行(标准线程)运行。 您正在启动线程,但是从不等待它们完成才测量时间。 我认为您可以在此处使用CyclicBarrier。

使用上述修复程序,我可以获得与ForkJoin和标准线程大致相同的时间。 而且它比顺序速度快三倍。 似乎合理。

PS:您正在做一个微基准测试。 阅读该问题的答案以提高基准精度可能会很有用:

  相关解决方案