在C语言中设置CPU相关性时遇到的问题

在C语言中设置CPU相关性时遇到的问题,c,linux,compiler-errors,cpu,compiler-warnings,C,Linux,Compiler Errors,Cpu,Compiler Warnings,我正在尝试计算CPUID指令运行所需的时间 资料来源: #include <stdio.h> #include <sched.h> cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(0, &mask); sched_setaffinity(0, sizeof(mask), &mask); static inline unsigned long long tick() { unsigned long lo

我正在尝试计算CPUID指令运行所需的时间

资料来源:

#include <stdio.h>
#include <sched.h>

cpu_set_t mask;

CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);

static inline unsigned long long tick()
{
    unsigned long long d;
    asm volatile ("rdtsc" : "=A" (d));
    return d;
}

void cpuid(void)
{
    int i;

    for(i=0; i != 5; i++)
    {
         asm volatile ("cpuid");
    }
}

int main()
{
    long long bef;
    long long aft;
    long long dif;

    bef=tick();
    cpuid();
    aft=tick();
    dif=aft-bef;

    printf("%d\n", bef);
    printf("%d\n", aft);
    printF("%d\n", dif);

    return 0;
}
我在不是文件的代码上出错! 例如:

test.c:6:1: error: expected identifier or '(' before 'do'
test.c:6:1: error: expected identifier or '(' before 'while'
test.c:7:1: error: expected identifier or '(' before '__extension__'
test.c:8:1: warning: data definition has no type or storage class [enable by def...
test.c:8:1: error: intializer element is not constant
定义。。。实际上输出不是因为我的终端窗口很小。我在ESXi工作

任何帮助都将是惊人的

给未来的读者

User@Iwillnotexist idotnotexist正确地说,使用以下函数可以获得完整的x86和x64支持

static __inline__ unsigned long long rdtsc(void)
{
  unsigned hi, lo;
  __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
  return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}

你有一个函数之外的代码。这是不允许的。将以下内容移到主菜单中:

cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);

你有一个函数之外的代码。这是不允许的。将以下内容移到主菜单中:

cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);

这些说明应包含在主目录中:

cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
这将修复编译错误

然后,cpuid的五次迭代太少,无法给出有意义的结果

您可以检查这一点,但只使用CPUID指令生成的两个不同长度的序列。你需要一个更长的周期,但不要太长,让内存进入游戏

我已经运行了一些测试,测试定义在5到1000之间;CPU亲和力似乎不会影响四核上的结果:

#include <stdio.h>
#include <sched.h>

static inline unsigned long long tick() {
    unsigned long long d;
    asm volatile ("rdtsc" : "=A" (d));
    return d;
}

static inline void cpuid(void) {
    int i;
    for(i=0; i != TEST; i++) {
         asm volatile ("cpuid");
    }
}

int main()
{
    long long bef, aft, dif;

    bef=tick();
    cpuid();
    aft=tick();
    dif=(aft-bef)/TEST;

    printf("%lld\n", dif);

    return 0;
}

gcc -o0 -DTEST=100 -D_GNU_SOURCE -W -Wall -o time time.c && ./time

这些说明应包含在主目录中:

cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
这将修复编译错误

然后,cpuid的五次迭代太少,无法给出有意义的结果

您可以检查这一点,但只使用CPUID指令生成的两个不同长度的序列。你需要一个更长的周期,但不要太长,让内存进入游戏

我已经运行了一些测试,测试定义在5到1000之间;CPU亲和力似乎不会影响四核上的结果:

#include <stdio.h>
#include <sched.h>

static inline unsigned long long tick() {
    unsigned long long d;
    asm volatile ("rdtsc" : "=A" (d));
    return d;
}

static inline void cpuid(void) {
    int i;
    for(i=0; i != TEST; i++) {
         asm volatile ("cpuid");
    }
}

int main()
{
    long long bef, aft, dif;

    bef=tick();
    cpuid();
    aft=tick();
    dif=(aft-bef)/TEST;

    printf("%lld\n", dif);

    return 0;
}

gcc -o0 -DTEST=100 -D_GNU_SOURCE -W -Wall -o time time.c && ./time


使用rdtsc和=A asm约束,您将犯下许多其他人在您之前犯过的相同错误。。。我明白这一点,但我说的对吗?RDTSC返回周期或实际时间都无关紧要。因为任何一种方式的差异都表明时间已经过去,所以它只是以实际时间或指定时间内的循环量进行测量。我可能错了。如果我是,你能解释一下吗?问题不在于此,问题在于RDTSC返回一个64位的值,但它在寄存器edx和eax中被分成hi和lo两半。在32位模式下,=A约束正确选择一对寄存器edx:eax;在64位模式下,它不会。相反,您将只阅读rax,其上半部分在rdtsc后为零。因此,当你进行减法运算时,有时你会在不应该的情况下得到负值,并且你无法测量超过几秒钟的时间差,因为你只使用TSC计数器的低位32位。如果你将代码更改为使用下面的rdtsc函数版本,而不是你自己的勾号,它可以在任何地方的32位和64位操作系统上运行。我有一个新问题。将此代码移植到windows:有什么想法吗?您将犯下许多其他人在使用rdtsc和=A asm约束之前犯过的相同错误。。。我明白这一点,但我说的对吗?RDTSC返回周期或实际时间都无关紧要。因为任何一种方式的差异都表明时间已经过去,所以它只是以实际时间或指定时间内的循环量进行测量。我可能错了。如果我是,你能解释一下吗?问题不在于此,问题在于RDTSC返回一个64位的值,但它在寄存器edx和eax中被分成hi和lo两半。在32位模式下,=A约束正确选择一对寄存器edx:eax;在64位模式下,它不会。相反,您将只阅读rax,其上半部分在rdtsc后为零。因此,当你进行减法运算时,有时你会在不应该的情况下得到负值,并且你无法测量超过几秒钟的时间差,因为你只使用TSC计数器的低位32位。如果你将代码更改为使用下面的rdtsc函数版本,而不是你自己的勾号,它可以在任何地方的32位和64位操作系统上运行。我有一个新问题。将这段代码移植到windows:有什么想法吗?好的,那么将亲和性的东西转移到主要作品中。我想做的是测量执行CPUID所需的时间。因为这是一条离开虚拟环境的指令。因此,我希望在VM中执行指令的时间会增加。我希望它们会是激烈的,因为我的研究旨在从VM中的可执行文件中识别虚拟环境。我还看到RDTSC在不一致的基础上返回负值!这就是为什么我决定设置CPU亲和力,以防指令通过内核,如果这样的话。我看到的dif大约为80000。这是否很大?@user3078629您是否看到我在w.r.t.上面的评论。在asm volatile rdtsc:=A d;为什么这是错误的?你一定要改变这一点。例如,这里的x86_64解决方案
这是一种方法。好吧,把亲和性的东西移到主要作品中。我想做的是测量执行CPUID所需的时间。因为这是一条离开虚拟环境的指令。因此,我希望在VM中执行指令的时间会增加。我希望它们会是激烈的,因为我的研究旨在从VM中的可执行文件中识别虚拟环境。我还看到RDTSC在不一致的基础上返回负值!这就是为什么我决定设置CPU亲和力,以防指令通过内核,如果这样的话。我看到的dif大约为80000。这是否很大?@user3078629您是否看到我在w.r.t.上面的评论。在asm volatile rdtsc:=A d;为什么这是错误的?你一定要改变这一点。例如,这里的x86_64解决方案是一种方法。