【问题标题】:C array = array faster than memcpy() [closed]C数组=数组比memcpy()快[关闭]
【发布时间】:2013-05-15 22:40:21
【问题描述】:

我有一段 C 代码正在尝试优化,其中涉及将数组 a 设置为 b。我目前正在使用 memcpy 来实现这一点,它可以工作,但是速度不够快。即

double a[4] = {1.0, 2.0, 3.0, 4.0};
double b[4];
memcpy(b, a, sizeof(a));

这是一个基本示例,我的程序类似,但最多使用 9000 个双打。我知道使用指针可以节省很多时间,但我不知道该怎么做。非常感谢您的帮助。

编辑:我不需要保留可以丢弃的 a 数组。我只需要从a转移到b。

【问题讨论】:

  • 如果你在复制数据,你就是在复制数据。如果能轻松击败memcpy,我会感到惊讶。
  • 数组对象被评估为 memcpy 函数中的指针。在 memcpy 中使用指针不会产生影响
  • 您应该首先查看您的设计,看看是否所有这些复制都是绝对必要的。
  • 如果复制后不需要a,但需要从a转移到b,为什么不使用a而不是b

标签: c pointers optimization memcpy


【解决方案1】:

我使用 b 中的值来确定 a 的新值。它通过 while 循环检查数据是否收敛。

在这种情况下,如果您来回切换数组,您也许可以避免任何复制,就像这样(与您编写的内容相反;根据需要进行调整):

double array1[SIZE], array2[SIZE];
double* a = array1, double* b = array2;
generate_initial_values(array1);

for (;;)
{
    // do either 
    memcpy(b, a, sizeof array1); // sizeof either array will do; *don't* use sizeof a or b, which is only the size of the pointer, not of the array
    update_values_in_b(b);

    // or, better:
    produce_modified_values_in_b_from_a(a, b);

    if (converged(a, b)) break;
    // switch arrays
    double* temp_ptr = a;
    a = b;
    b = temp_ptr;
}

如果适合你,第二种方式会更快。如果你必须使用 memcpy,你可以尝试Very fast memcpy for image processing? 中的东西,但可能对你来说最好的方法是使用 memcpy 并将编译器的优化级别设置得尽可能高。确保您 #include <string.h> 并且 memcpy 的 size 参数是编译时常量(它在上面),并查看生成的汇编代码以验证编译器是否内联副本。

编辑:等等,这是另一个想法,甚至不需要切换数组:

double a[SIZE], b[SIZE];
generate_initial_values(a);

for (;;)
{
    produce_modified_values_in_second_array_from_first(a, b);
    if (converged(a, b)) break;
    produce_modified_values_in_second_array_from_first(b, a);
    if (converged(b, a)) break;
}

当您退出循环时,您不知道哪个数组具有最新值,但如果它们已经收敛,您可能不在乎。如果你这样做了,你可以设置一个指向最新值的指针,或者使用一个函数:

void calling_function(void)
{
    ...
    double a[SIZE], b[SIZE];
    generate_initial_values(a);
    double* great_values = get_great_values(a, b); // returns either a or b
    ...
}

double* get_great_values(double* a1, double* a2)
{
    for (;;)
    {
        produce_modified_values_in_second_array_from_first(a1, a2);
        if (converged(a1, a2)) return a2;
        produce_modified_values_in_second_array_from_first(a2, a1);
        if (converged(a2, a1)) return a1;
    }
}

【讨论】:

  • 嗨,吉姆,谢谢,这就是我要找的。抱歉,我一开始没有完整解释:)
  • @NicholasCooke 我已经做得更好了......你可能根本不需要任何 memcpy......看看。
  • 是的,这很完美!谢谢!
  • @NicholasCooke 再看一看……我认为我在完美方面有所改进。
  • 顺便说一句,这是 XY 问题的经典示例(google it)。问题不在于 memcpy 或指针。
【解决方案2】:

如果memcpy() 不起作用,你就被卡住了。对于大型操作数,memcpy() 函数受内存限制,因此不可能* 击败它。唯一的选择是重新设计你的程序,这样它就不需要复制数组了。

(“Memory-bound”表示memcpy() 受限于您的 RAM 或内存控制器的速度。函数可以是 CPU-bound、memory-bound、IO-bound 等)

在大多数平台上,memcpy() 是用手动调整的汇编语言编写的,并经过大量优化以利用各种处理器功能(例如 SSE)。尝试使用多个内核是行不通的,因为即使您将工作分散到更多内核上,也不会将工作分散到更多 RAM 或更多内存控制器上。

脚注

* 某些平台或工具链的memcpy() 可能优化不佳。

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    相关资源
    最近更新 更多