【问题标题】:short short int in c?c语言中的short short int?
【发布时间】:2011-10-05 13:50:42
【问题描述】:

我正试图从我的记忆中挤出尽可能多的内容。 我有一个 4.9999995e13 整数矩阵,但它们只需要是真或假 - 基本上我只需要为这些整数中的每一个提供一点存储空间。

我知道 C 中没有单个位类型(也许有人可以向我解释原因),而且我也知道如果存在 short short int,它将是 1 个字节,与 char 相同。然而,C 中的所有逻辑运算都返回整数(以及一些其他函数)。

所以我的问题是:

  • 有没有办法让short short int 存在?
  • 如果我改用char,我是否会因为必须完成所有转换为int 而导致性能下降?
  • 还有其他我想念的方法吗?

以防万一,我正在为 C99 使用 GCC 进行编译。

编辑我刚刚在this wikipedia page 上看到有一个_Bool 类型,这实际上是标准的吗?

【问题讨论】:

  • 您能否解释一下为什么它们都必须转换为int
  • 您可以使用位域 (codepad.org/HMz2f7OR)。使用char 作为 C 中的位域底层类型是实现定义的(这就是为什么我没有将它作为答案发布,因为我现在不想为 unsigned int 创建 32 位域),但适用于 GCC。
  • 好吧,我不确定他们是否这样做,我认为按位 ORing 两个字符需要强制转换,因为它将返回一个 int,根据:en.wikipedia.org/wiki/Boolean_data_type#History
  • 这些位分别代表什么?例如,您打算如何访问 bit[4264334543] 的值,您将如何处理它?我问是因为可能有一种更有效的数据存储方式,这取决于您尚未透露的结构。
  • @AShelly 它们表示图中两个节点之间的边。我需要快速查找的值来查看是否存在边缘。

标签: c char boolean int short


【解决方案1】:

_Bool 类型在最新版本的 C 中是标准的,但这仍然不是您想要的,因为 _Bool 仍然占用至少一个字节(根据定义,char 也是如此)。

不,如果您想要那么多布尔位,您需要将它们打包到 bitfieldbit array 中。 C 中的位域没有标准数据类型,因此您还必须编写自己的宏或函数来获取特定偏移量的位。我还希望您将在具有大量 RAM 的 64 位机器上运行它,否则您将耗尽内存并且速度很快。

【讨论】:

  • 谢谢,这会给我的性能带来很大的影响吗?是的,目前有 32GB RAM 可用。
  • @Griffin,数据大小与您所拥有的一样大,将事物移入和移出内存的成本超过了执行成本。你没有 5e13 字节的内存,你的机器上只有 ~3e10,所以你可以做的任何事情都可以让数据集适合内存。
  • +1 实际上,我正在创建和分析非常大的图表。目的是获得 1e7 节点(我现在询问的顺序),但实际上即使是 1e6 的邻接矩阵也可能占用 58GB 或 RAM。我最终可以将所有这些移植到 OpenCL 并在大学的超级计算机上运行,​​但这仍然存在问题。我有很多事情要考虑。谢谢你让我睁大了眼睛!也为您的回答 +1。
  • @Griffin,如果您要这样做,邻接矩阵有更有效的数据结构,使用它们可能会将您的内存占用减少几个数量级。如果这就是您要构建的内容,您可以尝试提出一个单独的问题。
【解决方案2】:

您需要的是位图(或维基百科所称的bit array)。

没有short short int这样的东西,它只是一个char,它是C中最小的整数存储类。

使用这种方法可能会有一些性能开销,但这不是因为隐式转换为整数,而是因为操作位图比直接操作数组成员更棘手。

一个小例子可能有助于说明:

使用普通整数矩阵:

诠释垫[8 * 8]; // 假设行主要顺序 int is_element_set(int x, int y) { 返回垫子[y*8 + x]; }

使用位图:

unsigned char mat[8]; // assuming CHAR_BIT == 8
int is_element_set(int x, int y) { 
  return mat[y] & (1 << x);
}

【讨论】:

  • 谢谢,我宁愿减少空间效率也不愿影响性能,所以看来我已经尽我所能了?另外,由于我的位域大约有 5000000000000000 位,我可以将它存储在哪种类型中?
  • 您可以将其存储在5e13/8 字符或5e13/32 整数中。无论哪种方式 >~5 太字节 - 所以我肯定会考虑空间效率 - 将数据进出主内存不会很快。
  • 这是很多位。原则上,您会将其存储在 unsigned char mat[5000000000000000/CHAR_BIT] 中,但听起来您最好查看稀疏数据结构(如果您的数据是稀疏的)。
  • @Griffin 即使您的代码必须做更多的工作,在许多情况下,较小的空间可能会更有效,因为较小的数据可能适合缓存,这比在主缓存上运行快一个数量级记忆。您只能通过针对您的特定情况进行测量才能知道。
  • +1 回答您的问题。正如您从另一个答案中看到的那样,我有很多事情要考虑。感谢您的意见。
【解决方案3】:

您有大约 50 TB 的数据。您想一次将它们全部放入 RAM 中吗?使用多于一位的 RAM 来保存一位信息将是完全疯狂的,即便如此,您的计算机也必须与这个星球上最大的超级计算机一样大。忘记位打包的性能。您将不得不担心完全不同的事情。

【讨论】:

    【解决方案4】:

    5e13 大约是 5.6 TB 的存储空间,您只需要代表您的位域。可能有更好的方法来处理您的问题。

    【讨论】:

      【解决方案5】:

      也许您可以使用 ANSI C 中可用的位域结构的一些明智实现。

      类似这样的:

      typedef struct node_t_
      {
          char bit0 : 1;
          char bit1 : 1;
          char bit2 : 1;
          char bit3 : 1;
          char bit4 : 1;
          char bit5 : 1;
          char bit6 : 1;
          char bit7 : 1;
      } node_t;
      

      然后,您可以创建一些快速函数(可能是宏)来获取和设置此矩阵中的元素。不过,我从来没有实现过这样的东西。

      【讨论】:

        【解决方案6】:

        C99 stdbool.h 允许使用bool。但是这里你的问题是 4.9999995e13/8 会给出或多或少的 6.2500e+12 ($10^9$ 是 Gbyte,$10^12$ 是 Tbyte),所以你需要超过 6 Tbytes 的真实 + 虚拟内存(要幸运的)。这表明您做错了其他事情。您需要在可以使用更少内存处理的子问题中“扩展”您的问题。

        【讨论】:

          【解决方案7】:

          正如其他人所建议的,您可能应该使用位域。

          此外,如果您只是使用真/假值,并且其中一个值比另一个值少得多,请考虑使用隐式编码。您可以使用地图数据结构轻松完成此操作。当您使用图表时,如果您的图表非常稀疏,这将为您节省大量内存。如果将其与上面的位打包技术结合使用,您甚至可以将其全部放入 RAM。不过,在索引方面必须非常聪明。

          如果您不关心在处理过程中对性能造成影响(即,如果您更担心存储它而不是处理它),那么您可以做的另一件事是运行结构通过块中的压缩算法。有一个用于 bzip2 的 C 库,它可能会为您节省 90% 或更多类似的东西。缺点是这将花费(非常!)很长时间。您可能会从动态马尔可夫压缩 (DMC) 等按位压缩器中获得相当的性能,而且速度要快得多。

          【讨论】:

            【解决方案8】:

            我正试图从我的记忆中挤出尽可能多的内容。

            如果这是真的,那么您就不会浪费 8 位来存储 1 位的数据。你会使用位域。

            如果您对矩阵的内容类型有所了解,则可以使用其他优化。例如,如果您知道大多数矩阵通常设置为零,那么您可以只存储设置为 1 的元素的 x,y 对。

            如果没有,那么 4.9999995e13 将占用大约 6 TB 的 RAM!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-04-03
              • 1970-01-01
              • 2020-10-20
              • 1970-01-01
              • 1970-01-01
              • 2020-01-10
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多