C array =比memcpy()更快的数组

时间:2013-05-21 08:26:36

标签: c pointers optimization memcpy

我有一段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转移到b。

2 个答案:

答案 0 :(得分:8)

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

(“内存限制”表示memcpy()受RAM或内存控制器速度的限制。函数可以是CPU绑定的,内存绑定的,IO绑定的等等。)

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

脚注

* 某些平台或工具链的优化程度可能不高memcpy()

答案 1 :(得分:3)

  

我使用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;
    }
}