【问题标题】:Create a Data Hazard in a C Program在 C 程序中创建数据危害
【发布时间】:2014-12-07 12:41:33
【问题描述】:

我正在解决一个问题,我试图在不同的 C 程序中创建不同的场景,例如

  • 数据危害
  • 分支评估
  • 程序调用

这是在尝试学习流水线和出现的不同危险。

所以我正在编写简单的 C 程序并反汇编为汇编语言,以查看是否会产生危险。但我不知道如何制造这些危险。你们知道我该怎么做吗?这是我写的一些简单的代码。

我使用编译。

gcc -g -c programName.c -o programName.o
gcc programName.o -o programName
objdump -d programName.o > programName.asm

代码:

#include <stdio.h>
int main()
{
    int i = 0;
    int size = 5;
    int num[5] = {1,2,3,4,5};
    int sum=0;
    int average = 0;

    for(i = 0; i < size; i++)
    {
        sum += num[i];
    }

    average=sum/size;

    return 0;
}

...这里是它的程序集。

average.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   c7 45 f0 00 00 00 00    movl   $0x0,0xfffffffffffffff0(%rbp)
   b:   c7 45 f4 05 00 00 00    movl   $0x5,0xfffffffffffffff4(%rbp)
  12:   c7 45 d0 01 00 00 00    movl   $0x1,0xffffffffffffffd0(%rbp)
  19:   c7 45 d4 02 00 00 00    movl   $0x2,0xffffffffffffffd4(%rbp)
  20:   c7 45 d8 03 00 00 00    movl   $0x3,0xffffffffffffffd8(%rbp)
  27:   c7 45 dc 04 00 00 00    movl   $0x4,0xffffffffffffffdc(%rbp)
  2e:   c7 45 e0 05 00 00 00    movl   $0x5,0xffffffffffffffe0(%rbp)
  35:   c7 45 f8 00 00 00 00    movl   $0x0,0xfffffffffffffff8(%rbp)
  3c:   c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffffffffffc(%rbp)
  43:   c7 45 f0 00 00 00 00    movl   $0x0,0xfffffffffffffff0(%rbp)
  4a:   eb 10                   jmp    5c <main+0x5c>
  4c:   8b 45 f0                mov    0xfffffffffffffff0(%rbp),%eax
  4f:   48 98                   cltq   
  51:   8b 44 85 d0             mov    0xffffffffffffffd0(%rbp,%rax,4),%eax
  55:   01 45 f8                add    %eax,0xfffffffffffffff8(%rbp)
  58:   83 45 f0 01             addl   $0x1,0xfffffffffffffff0(%rbp)
  5c:   8b 45 f0                mov    0xfffffffffffffff0(%rbp),%eax
  5f:   3b 45 f4                cmp    0xfffffffffffffff4(%rbp),%eax
  62:   7c e8                   jl     4c <main+0x4c>
  64:   8b 55 f8                mov    0xfffffffffffffff8(%rbp),%edx
  67:   89 d0                   mov    %edx,%eax
  69:   c1 fa 1f                sar    $0x1f,%edx
  6c:   f7 7d f4                idivl  0xfffffffffffffff4(%rbp)
  6f:   89 45 fc                mov    %eax,0xfffffffffffffffc(%rbp)
  72:   b8 00 00 00 00          mov    $0x0,%eax
  77:   c9                      leaveq 
  78:   c3                      retq   

将不胜感激任何见解或帮助。谢谢!

【问题讨论】:

  • “数据危害”是什么意思?对于 DSP 芯片,当只允许一个时,这是在内部总线上运行两个数据源;你得到它是因为 DSP 芯片中的内容尽可能少,这迫使你,程序员,避免此类问题,对于 x86 芯片......它们有大量的晶体管;我认为他们不会允许发生数据危害。在 GCC 编译器相当不错的假设下,为什么认为它会生成具有这种定义数据危害的代码?
  • 您的其他可能定义是两个并行计算,它们以不安全的方式传递数据。单个C程序不是并行的,所以不会有这个问题。你认为你希望找到什么?
  • 这正是我想要弄清楚的。我正在大力尝试创建数据危害,例如 ADD R1、R4、R5 SUB R6、R2、R1,我已经创建了数据危害,但我无法使用 gcc 编译器重新创建数据危害。它适用于计算机体系结构课程。
  • “完全正确”?哪个定义?我建议两个。您的回答令人困惑;你展示 x6 代码,然后你谈论一个指令 ADD R1、R4、R5,它不是 x86 指令,所以你表现得好像你在谈论两个不同的事情。你清楚这些是不同的东西吗?您不会在 x86 指令集中遇到危险。你需要更清楚你的问题表述。

标签: c assembly pipelining


【解决方案1】:

由于这是作业,我不会给你一个直接的答案,而是一些深思熟虑的东西,以推动你朝着正确的方向前进。

x86 是一个糟糕的 ISA,用于尝试和理解流水线。一条 x86 指令可以隐藏两个或三个副作用,即使是最简单的流水线,也很难弄清给定指令的执行情况。你确定你没有提供一个 RISC ISA 来解决这个问题吗?

将您的循环/危险代码放入一个函数中,最好随机创建数组。使阵列更长。一个好的编译器基本上会找出答案并删除您编写的大部分代码!由于我不明白的原因,它会将您的变量放入内存中。

一个好的编译器也会做一些事情,比如循环展开,以试图隐藏数据危险并获得更好的代码调度。了解如何解决这个问题(或者如果可以的话,给编译器一个标志,告诉它如果允许乱搞编译器就不要做这些事情)。

关键字“volatile”对于告诉编译器不要优化/远离某些变量非常有帮助(它告诉编译器这个值可以随时改变,所以不要聪明,用它优化代码不要将变量保留在寄存器文件中)。

数据危险意味着管道将停止等待数据。通常指令会及时被绕过,因此不会发生停顿。想想哪些类型的指令可能无法被绕过,并可能导致数据危险的停顿。这取决于流水线,因此为特定处理器停顿的代码可能不会为另一个处理器停顿。现代无序英特尔处理器非常擅长避免这些停顿,而编译器则擅长重新调度代码,因此即使在有序内核上也不会发生这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 2021-04-10
    • 2016-07-22
    • 2019-06-03
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多