我正在尝试优化代码,以便在7秒内运行。我把它降到了8,现在我正在尝试使用指针加速代码。但是当我尝试编译时,gcc会出错:
.c:29:警告:从不兼容的指针类型.c:29分配: 警告:不同指针类型的比较缺少强制转换
这是我在尝试使用指针之前所拥有的:
#include <stdio.h>
#include <stdlib.h>
#define N_TIMES 600000
#define ARRAY_SIZE 10000
int main (void)
{
double *array = calloc(ARRAY_SIZE, sizeof(double));
double sum = 0;
int i;
double sum1 = 0;
for (i = 0; i < N_TIMES; i++) {
int j;
for (j = 0; j < ARRAY_SIZE; j += 20) {
sum += array[j] + array[j+1] + array[j+2] + array[j+3] + array[j+4] + array[j+5] + array[j+6] + array[j+7] + array[j+8] + array[j+9];
sum1 += array[j+10] + array[j+11] + array[j+12] + array[j+13] + array[j+14] + array[j+15] + array[j+16] + array[j+17] + array[j+18] + array[j+19];
}
}
sum += sum1;
return 0;
}
这是我使用指针时所拥有的(此代码生成错误):
int *j;
for (j = array; j < &array[ARRAY_SIZE]; j += 20) {
sum += *j + *(j+1) + *(j+2) + *(j+3) + *(j+4) + *(j+5) + *(j+6) + *(j+7) + *(j+8) + *(j+9);
sum1 += *(j+10) + *(j+11) + *(j+12) + *(j+13) + *(j+14) + *(j+15) + *(j+16) + *(j+17) + *(j+18) + *(j+19);
}
如何修复此错误?顺便说一下,我不希望有关于尝试优化代码的替代方法的建议。这是一个家庭作业问题,限制了我被允许做的事情。我认为一旦我将这个指针固定,它将在7秒内运行,我会很高兴。
答案 0 :(得分:2)
不同指针类型的比较缺少一个演员
这意味着您尝试将一种类型的指针与另一种类型的指针进行比较,并且没有强制转换。
double *array = calloc(ARRAY_SIZE, sizeof(double));
int *j;
指向double
的指针和指向int
的指针无法直接比较。出于这个原因,您不能将j
与array
进行比较。也许您打算将j
声明为指向double
?
答案 1 :(得分:0)
C是一种静态类型语言,跨指针类型的比较会给你带来错误。在某些情况下会有一些隐式转换,比如将double与int进行比较,因为比较数字是一种常见的操作。比较不同类型的指针不是。
此外,当您在数组上增加指针时,它会使用其取消引用元素的大小来了解内存移动的距离。在一系列双精度数上移动int将导致问题。
double会移动到一个int,所以无论如何你都会得到更多与int指针的交互。
你可以明确地投射东西,但实际上你应该使用双*来表示双打数组。
答案 2 :(得分:0)
如果从数组表示移动到指针表示会产生很多(如果有的话)加速,我会非常惊讶,因为它们都是最终输出代码中的内存地址(和内存偏移)。请记住,数组表示实际上也是不同服装中的指针表示。
相反,我会考虑两种技巧之一:
嵌入式MMX表示,用于在同一时钟周期内在同一寄存器中执行多个加法运算。然后,您需要在结尾附近进行一次操作,以将高双和低双合并。
分散/收集算法以在多个核心上扩展添加操作(现在几乎每个CPU都有4个核心,如果不是16个伪核心(超线程))
除此之外,您可以尝试缓存分析,并将中间体存储在不同的寄存器中。在每个计算中似乎都有一个深层次的添加链。打破它们可能会产生将on-cpu存储扩展到更多寄存器的能力。
大多数操作都会受到内存限制。 20是循环展开的一个非常奇怪的边界。双打可能是16位,因此20位双精度是320位,这可能与您的内存缓存行大小不对齐。尝试确保展开的多个循环与您的体系结构的1级缓存完全对齐,并且可以避免在跨缓存边界读取时发生页面错误。这样做会加快一些人的程序速度(但谁知道多少)。
答案 3 :(得分:0)
“当你在一个数组上增加指针时,它会使用它的解引用元素的大小来知道内存移动的距离。在一个双精度数组上移动一个int会导致问题”。
为避免警告:请执行以下操作
for (j= (int *)array; j < (int *)&array[ARRAY_SIZE]; j += 20)