2

我正在尝试在 Ubuntu 8.10 上使用 RDTSC(我尝试过的其他分析软件无法达到我需要的分辨率)来计时代码。但是,我不断收到来自任务切换和中断触发的异常值,这导致我的统计数据无效。

考虑到我的程序在几毫秒内运行,是否可以在我的环境中禁用所有中断(这会固有地关闭任务开关)?还是我需要去一个可以让我拥有更多权力的操作系统?使用我自己的操作系统内核来执行这个计时代码会更好吗?我试图证明算法的最佳/最差情况性能,因此它必须完全符合时间要求。

我目前使用的相关代码是:

inline uint64_t rdtsc()
{
    uint64_t ret;
    asm volatile("rdtsc" : "=A" (ret));
    return ret;
}

void test(int readable_out, uint32_t start, uint32_t end, uint32_t (*fn)(uint32_t, uint32_t))
{
    int i;
    for(i = 0; i <= 100; i++)
    {
        uint64_t clock1 = rdtsc();
        uint32_t ans = fn(start, end);
        uint64_t clock2 = rdtsc();

        uint64_t diff = clock2 - clock1;

        if(readable_out)
            printf("[%3d]\t\t%u [%llu]\n", i, ans, diff);
        else
            printf("%llu\n", diff);
    }
}

给那些注意到我没有正确处理此代码中的溢出条件的人加分。在这个阶段,我只是想获得一致的输出,而不会因为我的程序丢失时间片而突然跳跃。

我的程序的好值是-20。

回顾一下,我是否可以在不中断操作系统的情况下运行此代码?还是我需要在 ring0 的裸硬件上运行它,这样我才能禁用 IRQ 和调度?提前致谢!

4

7 回答 7

3

如果您在每次测试迭代之前立即调用 nanosleep() 休眠一秒钟左右,您应该为每个测试获得一个“新鲜”的时间片。如果您使用 100HZ 定时器中断编译内核,并且您的定时功能在 10 毫秒内完成,那么您应该能够避免定时器中断以这种方式击中您。

为了最大限度地减少其他中断,请取消配置所有网络设备,配置您的系统而不进行交换,并确保它处于静止状态。

于 2009-08-01T03:25:18.797 回答
2

棘手。我认为您不能“关闭”操作系统并保证严格的调度。

我会把它颠倒过来:鉴于它运行得如此之快,运行它多次以收集结果分布。鉴于标准 Ubuntu Linux 不是狭义上的实时操作系统,所有替代算法都将在相同的设置中运行 --- 然后您可以比较您的分布(使用从汇总统计到分位数到 qqplots 的任何内容)。您可以与 Python、R 或 Octave 进行比较……以最适合您的为准。

于 2009-08-01T03:02:35.620 回答
2

你也许可以摆脱运行FreeDOS,因为它是一个单进程操作系统

这是第二个链接中的相关文本:

Microsoft 的 DOS 实现是 x86 世界中 DOS 系统的事实标准,它是一个单用户、单任务操作系统。它提供对硬件的原始访问,并且仅提供用于文件 I/O 之类的 OS API 的最小层。对于嵌入式系统来说,这是一件好事,因为您通常只需要在没有操作系统的情况下完成某些事情。

DOS(本机)没有线程的概念,也没有多个正在进行的进程的概念。应用软件通过使用中断接口进行系统调用,调用各种硬件中断来处理视频和音频等事情,调用软件中断来处理各种事情,比如读取目录、执行文件等等。

当然,实际上将 FreeDOS 引导到实际硬件上,而不是在模拟器中,您可能会获得最佳性能。

我实际上并没有使用过FreeDOS,但我假设由于您的程序似乎是标准 C,您将能够使用 FreeDOS 的任何标准编译器。

于 2009-08-01T03:09:16.063 回答
2

如果您的程序以毫秒为单位运行,并且您在 Linux 上运行,请确保您的计时器频率(在 linux 上)设置为 100Hz(而不是 1000Hz)。(cd /usr/src/linux; make menuconfig,然后查看“处理器类型和功能”->“定时器频率”)这样你的 CPU 将每 10 毫秒中断一次。

此外,考虑到 Linux 上的默认 CPU 时间片是 100 毫秒,因此如果您的级别为 -20,那么如果您运行几毫秒,您将不会被取消调度。

此外,您在 fn() 上循环了 101 次。请考虑将 fn() 设置为无操作以正确校准您的系统。

进行统计(平均 + stddev)而不是打印太多次(这会消耗您预定的时间片,并且终端最终将获得计划等......避免这种情况)。

RDTSC 基准测试示例代码

于 2009-08-01T03:16:17.080 回答
1

您可以使用chrt -f 99 ./test以最大实时优先级运行 ./test。那么至少它不会被其他用户空间进程中断。

此外,安装linux-rt软件包将安装一个实时内核,这将使您能够通过线程中断更好地控制中断处理程序的优先级。

于 2009-08-01T03:09:21.693 回答
0

如果您以 root 身份运行,您可以调用 sched_setscheduler() 并给自己一个实时优先级。检查文档。

于 2009-08-01T03:04:50.623 回答
0

也许有一些方法可以禁用 linux 上的抢占式调度,但可能不需要它。您可能会使用来自/proc/<pid>/schedstat或其他对象的信息/proc来感知您何时被抢占,并忽略这些时序样本。

于 2009-08-01T03:26:18.250 回答