【问题标题】:What is the most efficient way to merge byte arrays in C?在 C 中合并字节数组的最有效方法是什么?
【发布时间】:2011-02-07 12:47:49
【问题描述】:

假设我有两个 char 数组,每个位置都是 1 或 0。 这两个数组是在不同的进程中计算出来的,然后发回一个master进行合并,所以每个数组只写到他们数组的一定范围内:

p1 : [0, 0, 0, 0, 1, 1, 0, 1]

p2 : [1, 0, 1, 1, 0, 0, 0, 0]

目标:[1, 0, 1, 1, 1, 1, 0, 1]

但是,这些可能是非常大的数组。除了循环其中一个之外,有没有一种超级快速的方法?

为了澄清,它们应该是 OR'd。

【问题讨论】:

  • 您必须将 0 和 1 作为字符发送吗?在将它们发送给主机之前,您可以将它们打包成整数吗?然后你可以对master中的两个整数进行异或。
  • @Makis,这是一个简洁的微优化,但如果它们是连续的范围,它对大范围毫无帮助 - 你只会浪费很多 x ^ 00 ^ x 操作。如果每个进程负责的位是交错的,那将是一个好主意。
  • 是的,我想我可以使用位数组或整数之类的东西……我只使用了 char,因为它是一个字节,并且实现非常简单。
  • 你的问题不是很清楚 - 当你说“合并”时,你只是将这些数组 OR-ing 在一起吗?

标签: c arrays


【解决方案1】:

假设字节粒度足够好,您可能希望使用memcpy 将它们复制到输出数组中:

memcpy(goal, p2, 4);
memcpy(goal + 4, p1 + 4, 4);

您可以通过让p1p2 仅包含它们自己的范围来进一步优化这一点,例如:

char p1[4] = { 1, 1, 0, 1 };
char p2[4] = { 1, 0, 1, 1 };
char goal[8];
memcpy(goal, p2, 4);
memcpy(goal + 4, p1, 4);

请注意,您可能还想研究位向量打包 - 您将八位打包到每个字符中。这将为大型数组节省大量内存,尽管它使访问变得复杂。

【讨论】:

  • 我也许可以这样做,但对我来说,下一步是让工作处理器相互结合,然后再将其发送给主处理器。与一次大分配相比,重新分配几次小时间会产生任何开销吗?
  • 是的,会有开销。您最好使用共享内存并将它们全部写入最终目标数组。
  • 如果处理器分布在多台机器上,则不会:P
  • 那么最好直接将结果传递给主人,我想。毕竟,在任何情况下,主服务器都会收到相同数量的数据。只要确保你只发送每个从属负责的范围(不是整个数组,其中大部分是空白的)
【解决方案2】:

我建议:

  1. 分析以确保这确实是一个瓶颈。
  2. 研究这种“矢量样式”,即对齐字节数组,然后使用常规线性循环处理尽可能多的字节,使用单机操作,可能通过以unsigned long long 访问。
  3. 重新排列,以便子进程以更有效的格式报告,可能使用某种运行长度压缩。

【讨论】:

    【解决方案3】:

    如果你在不同的处理器上工作也许你应该考虑使用 MPI 库进行归约操作,它非常快

    MPI_Reduce(p, goal, size, MPI_CHAR, MPI_LOR, goal_process_id, MPI_COMM_WORLD);
    

    如果您使用不同的线程,那么 OpenMP 在代码简单性方面也不错(这是快速而肮脏的代码):

    #pragma omp parallel for reduction(|, out)
    for(int i=0; i<size; i++)
      out[i] = p1[i] * p2[i];
    

    【讨论】:

      【解决方案4】:

      为什么使用数组有什么原因吗?因为就速度和内存消耗而言,最有效的方法无疑是在字节级别上实际工作。而不是不必要地来回折腾数组。

      也许是这样的?

      uint8 proc_n (void)
      {
        uint8 result = 0x00;
        uint8 i;
      
        for(i=0; i<8; i++)
        {
          if(something)
          {
            result |= (0x01 << i);
          }
        }
      
        return result;
      }
      
      
      
      typedef uint8 (*Proc_ptr)(void);
      
      Proc_ptr proc_array [PROCESSES] =
      {
        proc_1,
        proc_2,
        ...
      };
      
      uint8 result = 0x00;
      
      for(i=0; i<PROCESSES; i++)
      {
        result |= proc_array[i]();
      }
      

      【讨论】:

        猜你喜欢
        • 2020-09-07
        • 1970-01-01
        • 2023-03-17
        • 2014-04-01
        • 1970-01-01
        • 2021-08-17
        • 2020-09-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多