我有一个函数来计算C ++中的点积。我想使用-O3编译器优化来编译此函数。我的代码库中的其余代码都是使用-O0编译的。为此,我创建了一个包含函数的静态库,并使用-O3编译了该库。然后,我将库链接到我的代码。但是我没有从库中获得优化。
test.cpp
#include "config.h"
int multiply(uint128 *X1, uint128 *Y1, uint128 &ans, int input_length)
{
int i=0;
ans = 0;
if (input_length > 4)
{
for (; i < input_length - 4; i += 4)
{
ans += X1[i] * Y1[i];
ans += X1[i + 1] * Y1[i + 1];
ans += X1[i + 2] * Y1[i + 2];
ans += X1[i + 3] * Y1[i + 3];
}
}
for (; i < input_length; i++)
{
ans += X1[i] * Y1[i];
}
return 0;
}
int main()
{
int len = 500, wrapper = 50;
uint128 a[len], b[len], ans;
auto start = time_now, end = time_now;
long long ctr = 0;
for(int t = 0; t < wrapper; t++)
{
for(int i =0; i < len; i++)
{
a[i] = rand();
b[i] = rand();
}
start = time_now;
multiply(a, b, ans, len);
end = time_now;
ctr += std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count();
}
cout<<"time taken: "<<ctr<<endl;
}
Compilation:
g++ -O3 test.cpp -std=c++11
./a.out
time taken: 1372
optimized.hpp
#ifndef OPTIMIZED_HPP
#define OPTIMIZED_HPP
#include <bits/stdc++.h>
using namespace std;
typedef __uint128_t uint128;
int multiply(uint128 *X1, uint128 *Y1, uint128 &ans, int input_length);
#endif
main.cpp
#include "optimized.hpp"
typedef __uint128_t uint128;
#define time_now std::chrono::high_resolution_clock::now()
int main()
{
int len = 500, wrapper = 50;
uint128 a[len], b[len], ans;
auto start = time_now, end = time_now;
long long ctr = 0;
for(int t = 0; t < wrapper; t++)
{
for(int i =0; i < len; i++)
{
a[i] = rand();
b[i] = rand();
}
start = time_now;
multiply(a, b, ans, len);
end = time_now;
ctr += std::chrono::duration_cast<std::chrono::nanoseconds>(end-start).count();
}
cout<<"time taken: "<<ctr<<endl;
return 0;
}
Compilation:
(the name of the library file is optimized.cpp)
g++ -O3 -g -std=c++11 -c optimized.cpp
ar rcs libfast.a optimized.o
g++ main.cpp libfast.a -std=c++11 -O3
./a.out
time taken: 36140
恐怕您犯了上课的脚步:我优化了试图计时的功能。我们都做了一次。
您已经优化了程序-O3
。编译器发现程序忽略multiply
的返回值。它还具有multiply
的定义并观察到,除了(忽略的)返回值之外,主体没有外部影响。所以这行:
multiply(a, b, ans, len);
也可能是:
(void)0;
和优化器将其剔除。
您可以通过修改程序来纠正此问题,以便它使用返回值multiply
的值总是以某种方式有助于程序的输出。
但是那还不够。 -O3
优化test.cpp
时编译器可以看到multiply
的定义仍然要与main.cpp
的相同优化相比,这是一个主要的信息优势,其中multiply
只是对黑匣子的外部引用。
用multiply
有意义地测量-O3
的速度您必须在-O0
优化中针对其速度进行优化每种情况在其他条件相同的情况下。所以至少这样做:
$ g++ -Wall -Wextra -pedantic -c -O0 -o mult_O0.o optimized.cpp
$ g++ -Wall -Wextra -pedantic -c -O3 -o mult_O3.o optimized.cpp
$ g++ -Wall -Wextra -pedantic -c -O3 -o test.o test.cpp
test.cpp: In function ‘int main()’:
test.cpp:13:13: warning: ISO C++ forbids variable length array ‘a’ [-Wvla]
13 | uint128 a[len], b[len], ans;
| ^
test.cpp:13:21: warning: ISO C++ forbids variable length array ‘b’ [-Wvla]
13 | uint128 a[len], b[len], ans;
| ^
((您可能会在意这些警告)
$ g++ -o tmult_O0 test.o mult_O0.o
$ g++ -o tmult_O3 test.o mult_O3.o
$ ./tmult_O0
time taken: 228461
$ ./tmult_O3
time taken: 99092
这表明-O3
正在执行其工作。
如果这样,您不需要需要使用返回值multiply
中test.cpp
的值,因为编译器现在看不到黑盒multiply(a, b, ans, len)
没有副作用,无法剔除它。