【问题标题】:Is there a CPU that can change variables simultaneously?是否有可以同时更改变量的 CPU?
【发布时间】:2009-10-23 20:18:38
【问题描述】:

如果我写:

a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
f = 0;

我认为(可能是错误的)CPU 会逐行运行,例如:

CPU says:
let me assign a to 0
then let me assign b to 0
then let me assign c to 0
then let me assign d to 0
etc...

我只是想知道是否有一个处理器可以同时更改变量...?

谢谢... 是的

【问题讨论】:

  • 你说的是什么语言?
  • 除非这是某种异国语言,否则这些不是对任何事物的“调用”。
  • 目的是什么?堆叠这些可能会产生一些意想不到的副作用。
  • 现代 CPU 是顺序执行指令的设备,一个接一个,读取数据,更改它,然后写回它。 SIMD 操作也是顺序的;区别只是它们的原子数据单元恰好是(比如说)128 位宽,大到足以存储四个浮点数。这种架构被称为冯诺依曼机器,虽然其他设计在理论上是可能的,但没有一个被建造和大量销售。
  • @Crashworks - 实际上,现代 CPU 几乎总是超标量,这意味着它们每个时钟周期可以执行多条指令(主要取决于指令和可用功能单元之间的依赖关系)。

标签: c variables


【解决方案1】:

你所拥有的是一行代码,而不是一个方法调用。

编辑:针对您编辑的问题...您需要的是矢量处理器(下面将详细讨论)。我记得这个想法是,你有一系列的值,你可以同时对所有这些值重复、并行地执行相同的操作。它们通常用于大型数学/物理、模拟和图形类型的东西(包括 PC/控制台 3D 图形,我认为)。

如果我没记错的话,在 C 语言中,您可以在一个“代码行”上粘贴多个语句,如下所示:

int a, b, c;
a = 1, b = 2, c = 3;

但是,这与写作没有什么不同:

int a, b, c;
a = 1; b = 2; c = 3;

这又是相同的

int a, b, c;
a = 1;
b = 2;
c = 3;

所有这些都在编译器中转换为相同的东西。因此,虽然其中一个只使用一个句法“语句”,并且其中两个写在一行上,但除了语法之外,它们都是相同的。

有些语言可以通过一次调用该语言的正常基本元素之一来生成多个值;例如,在 Lisp 中,您可以使用 maphash 对哈希表的每个元素运行相同的函数,如果该函数再次写回哈希表,那么一个“代码行”正在写入许多值。但这是一个毫无意义的衡量标准,因为那一行代码在后台运行了很多东西。

可能一个更好的例子是某些并行编程模型。矢量处理器旨在允许您同时并行地在 (4/8/16/N) 不同的数据元素上运行一条指令;您可以有意义地说它正在做您要问的事情,但是您需要学习如何在汇编中为向量机编写代码。此外,一些并行编程模型假设您有一段并行代码同时在 N 个线程中运行,从 N 个不同的输入数据集开始,并为每一个计算正确的输出。模型的任何实现都应该能够保证不同的执行在代码中的特定点“聚集在一起”,在这些点上,一切都同步起来,它们可以读取其他进程的数据并对其采取行动。

所以,呃,是的,这可能是一个非常简单的问题,也可能是一个非常深奥的问题,这取决于你想去兔子洞多远。

【讨论】:

  • 有道理...是的...我在玩物理和 C 并且这个问题出现了,因为有时有超过 50 个对象需要不断更新(重力、摩擦力等)。 ..) 如果一个进程可以改变所有这些属性,那就太酷了。
  • 嗯,重要的是要记住,如果您想同时更新 50 个项目,您需要有 50 个硬件来执行该更新。即使该语言假装您正在使用一个“命令”执行此操作,也可以这么说,它可能只是将其翻译成一次完成的 50 条指令。这就是 Lisp 案例中发生的情况。
  • SSE 和 AltiVec 在一条指令中对多个数据项进行操作
  • @Swegi,很高兴知道。对于这个问题的上下文很重要的一件事是,例如 C++ 中的程序员如何访问所述机器指令。如果有意义,编译器会排列它吗?什么样的代码可能会以这种方式得到优化?还是程序员需要内联一些程序集才能做到这一点?
【解决方案2】:

除非分配发生在数据库或其他一些支持事务的软件中,否则您提供的两个代码示例将很可能会导致 CPU 执行 100% 相同的指令

例如它们将被编译器/解释器转换成完全相同的操作码序列。

更新:

  1. 需要明确的是,正如其他人所指出的,a = b = c = 0; 只是 C(和其他语言)的语法糖,实际上可以转换为:

    c = 0; b = c; a = b;
  2. 可能存在语言/框架,其中 3 个分配是“原子的”,即作为事务一次全部执行,如果这就是您所说的“1 个调用”的话。最明显的例子是 SQL,其中说 UPDATE table SET a=0,b=0,c=0 ... 实际上不仅保证 3 次更新作为一个“调用”发生,而且是一个事务——要么全部更新,要么没有。

【讨论】:

    【解决方案3】:

    我想你可能有点困惑。您甚至无法使用线程来实现这一点。你所说的“电话”到底是什么意思?一行代码?第一行只是在许多类似 C 的语言中声明时提供的一种便利。

    我的意思是,您可以创建某种函数,该函数通过引用获取变量列表,然后是值列表,然后您可以调用该函数。我不确定你想要完成什么。

    但是不,没有一个语句不使用大多数 C 语言(您没有指定语言)中的函数,除非您希望所有变量具有相同的值(即 @987654321 @)。

    【讨论】:

      【解决方案4】:

      为什么不将值放在数组中并使用 memset 或 ZeroMemory 宏(在内部使用 memset。

      【讨论】:

      • 这是一个很好的观点。在某些机器上,memset() 实际上可能使用 DMA 控制器或其他访问内存的特殊方式来大大加快归零速度。不过仍然不太可能同时发生。
      【解决方案5】:

      也许不是 CPU,但这可以通过 FPGA 轻松完成。

      例如,有一种类似 C 的语言 Handel C 用于 FPGA 开发。因为代码被翻译成硬件,所以语句级别的真正并行性是可能的。

      Handle C 具有 parseq 构造,它们确定语句是并行发生还是顺序发生。 par 块的执行时间是最慢语句(或嵌套块或调用)的执行时间,变量赋值需要 1 个时钟周期,所以:

      // Three assignments in one clock
      par
      {
         a = 1;
         b = 2;
         c = 3;
      }
      
      // Three assignments in three clocks
      seq
      {
         a = 1;
         b = 2;
         c = 3;
      }
      

      其中一个有趣的功能是,例如,如果您有:

      par
      {
        a++ ;
        b = a ;
      }
      

      分配给 b 的值是 par 块 before 的值,因为它们同时发生(并且语句的顺序无关紧要)。使用此功能可以实现流水线执行,以便需要多个时钟周期的复杂算法可以在每个 个时钟周期生成结果(尽管会因流水线长度而延迟)。

      【讨论】:

        【解决方案6】:

        虽然与上面的代码没有严格相关,但它只是人类可读的指令表示,只要翻译保持特定语言和环境的定义语义,就可以翻译成任何机器代码。 .

        智能编译器可以翻译: int8 c = 1, c = 2; 到单个 int16 赋值(可能将两个值存储在单个寄存器中)如果它被写入这样做。另一方面,int16 d = 4; 在 8 位硬件上可能需要多个周期(读取:非原子)。去图吧。

        是的,某些 CPU 可以在原子(“同时”)操作中更改两个变量(多个存储槽)。

        其中最常见的为硬件安全同步提供了基础。

        CMPXCNG - Compare and Exchange

        CMPSWP - Compare and Swap

        为了多年来的优化(甚至不包括为矢量化处理等设计的系统),如果没有找到更专业的指令,我会感到惊讶。此外,虽然比简单的分配更远,但上下文切换和寄存器文件交换也可以原子地完成。

        【讨论】:

        • 这是我在这里看到的第一个正确答案。其他人都在选择 C ​​语法并缺少原子性约束。核心点是您需要查看您的 CPU 支持哪些特定的原子操作(x86-64 CPUS 可以一直执行到 128 位),在汇编中编写您的原子更新,然后将您的 C 变量映射到该内存中使用联合或诸如此类的东西。
        【解决方案7】:

        如果你真的想知道硬件层面发生了什么,那是一个非常深奥的话题。您是正确的,分配(很可能)不会同时发生。更糟糕的是,它们可能不会按照您最初指定的顺序发生。

        编译器和硬件保证从单个线程的角度来看,代码的行为就像它是按顺序执行的一样。但是为了使代码执行得更快,他们可以打破其他线程的这种错觉。在多 CPU 或多核环境中尤其如此。

        或者,如果您真正感兴趣的是如何加速您的代码:首先学习使用分析器并找出如何衡量您的代码慢的地方。我保证它不会在你期望的地方。然后,为了加速你的物理模拟代码,开始阅读你的编译器最有可能为你的 CPU 提供的向量内在函数。您无需学习如何使用汇编语言进行编程。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-13
          • 2022-01-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多