Vì mục đích giáo dục, tôi muốn biết cần bao nhiêu chu kỳ CPU để thực thi một chức năng sau khi tối ưu hóa (ở các cấp độ khác nhau) và biên dịch. Có cách nào để phân tích mã hoặc thực thi để có được câu trả lời có thể lặp lại không? Tôi đang sử dụng Eclipse Luna và MinGW trên Windows 7 Pro 64 bit.
#include
#include "main.h"
#define EPS 1e-15 // EPS một số nhỏ ~ độ chính xác của máy
#define R2D 57.295779513082320876798154814105 //nhân radian với R2D để lấy độ
#define D2R 0,01745329251994329576923690768489 //nhân độ với D2R để lấy radian
#define TWO_PI 6.283185307179586476925286766559 //2*Pi
double _stdcall CourseInitial (double *lat1, double *lon1, double *lat2, double *lon2)
{
radLat1 kép = D2R * *lat1;
radLat2 kép = D2R * *lat2;
radDeltaLon kép = D2R * (*lon2 - *lon1);
tc kép = 0;
if (cos(radLat1) < EPS) { // EPS một số nhỏ ~ độ chính xác của máy
nếu (radLat1 > 0) {
tc = 180; // Bắt đầu từ cực N
} khác {
tc = 0; // Bắt đầu từ cực S
}
} khác {
// Tính đúng khóa học [-180, 180)
tc = R2D * atan2(sin(radDeltaLon),
cos(radLat1) * tan(radLat2) - sin(radLat1) * cos(radDeltaLon)
);
}
if (fabs(tc) < EPS) {
tc = 0; // Ngăn fmod(tc, 360) trả về 360 do lỗi làm tròn
} khác {
tc += 360; //tc [180, 540)
}
return fmod(tc, 360); // trả về tc [0, 360)
}
int main(void)
{
vĩ độ kép1 = 67
doublelon1 = 15;
vĩ độ kép2 = 71;
doublelon2 = 24;
tc kép = 0;
tc = CourseInitial(&lat1, &lon1, &lat2, &lon2);
printf("Tiến trình từ điểm 1 đến điểm 2 là: %.1f\n", tc);
return 0;
}
我这样做了:
#include
#include
#include
#define EPS 1e-15 // EPS một số nhỏ ~ độ chính xác của máy
#define R2D 57.295779513082320876798154814105 //nhân radian với R2D để lấy độ
#define D2R 0,01745329251994329576923690768489 //nhân độ với D2R để lấy radian
#define TWO_PI 6.283185307179586476925286766559 //2*Pi
CourseInitial đôi (double *lat1, double *lon1, double *lat2, double *lon2)
{
radLat1 kép = D2R * *lat1;
radLat2 kép = D2R * *lat2;
radDeltaLon kép = D2R * (*lon2 - *lon1);
tc kép = 0;
if (cos(radLat1) < EPS) { // EPS một số nhỏ ~ độ chính xác của máy
nếu (radLat1 > 0) {
tc = 180; // Bắt đầu từ cực N
} khác {
tc = 0; // Bắt đầu từ cực S
}
} khác {
// Tính đúng khóa học [-180, 180)
tc = R2D * atan2(sin(radDeltaLon),
cos(radLat1) * tan(radLat2) - sin(radLat1) * cos(radDeltaLon)
);
}
if (fabs(tc) < EPS) {
tc = 0; // Ngăn fmod(tc, 360) trả về 360 do lỗi làm tròn
} khác {
tc += 360; //tc [180, 540)
}
return fmod(tc, 360); // trả về tc [0, 360)
}
cấu trúcLatLon
{
vĩ độ đôi, vĩ độ;
};
cấu trúc CoursePoint
{
LatLon a, b;
};
const int KÍCH THƯỚC = 1000000;
CoursePoint cps[SIZE];
đôi tc[SIZE];
LatLon Ngẫu nhiênLatLon()
{
LatLon l;
l.lat = Rand() % 90;
l.lon = rand() % 60;
trả lại l;
}
tĩnh __inline__ không dấu dài dài rdtsc(void)
{
không dấu chào, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
}
int main(void)
{
for(int i = 0; i < SIZE; i++)
{
cps[i].a = RandomLatLon();
cps[i].b = RandomLatLon();
}
unsigned long long t = rdtsc();
for(int i = 0; i < SIZE; i++)
{
tc[i] = CourseInitial(&cps[i].a.lat, &cps[i].a.lon, &cps[i].b.lat, &cps[i].b.lon);
}
t = rdtsc() - t;
printf("Thời gian=%f\n", t/(double)SIZE);
tổng gấp đôi = 0;
for(int i = 0; i < SIZE; i++)
{
tot += tc[i];
}
printf("Tổng các khóa học: %f\n", tot);
return 0;
}
Mỗi lần lặp mất khoảng 850-1000 chu kỳ.
Nếu bạn không chạy các vòng lặp dài như thế này, những nội dung giả sẽ ảnh hưởng đến hiệu suất thực. Các tùy chọn tối ưu hóa trình biên dịch tạo ra sự khác biệt nhỏ và việc thêm -ffast-math sẽ tạo ra sự khác biệt lớn hơn -O0 so với -O3. Trình biên dịch khác nhau cũng sẽ khác nhau.
g++ 4.9.2:
-O0 1013 chu kỳ
-O1 879 chu kỳ
-O2 878 chu kỳ
-O3 877 chu kỳ
Thêm -ffast-toán:
-O0 978
-O1 855 (chạy lại được 890)
-O2 882
-O3 848 (chạy lại được 850)
Clang++ (3.7 vài tuần trước):
-O0 998 chu kỳ
-O1 954 chu kỳ
-O2 955 chu kỳ
-O3 957 chu kỳ
Thêm -ffast-toán:
-O0 967
-O1 872
-O2 865
-O3 875
Clang++ kể từ ngày hôm qua:
-O0 1001 chu kỳ
-O1 956 chu kỳ
-O2 948 chu kỳ
-O3 949 chu kỳ
Thêm -ffast-toán:
-O0 969
-O1 871
-O2 869
-O3 873
Lưu ý rằng sự khác biệt nhỏ hơn 10 chu kỳ đồng hồ có thể không có ý nghĩa thống kê. Tôi đã báo cáo một lần chạy, nhưng trước đó tôi đã thử nó vài lần để đảm bảo rằng tôi luôn nhận được cùng một câu trả lời.
Lưu ý rằng các bộ xử lý khác nhau cho kết quả rất khác nhau và các phiên bản trình biên dịch khác nhau cho thấy rõ một số khác biệt.
EDIT: Để giải trí, tôi sẽ viết lại nó thành Pascal và chạy nó qua trình biên dịch Pascal của tôi để xem nó làm gì.
Mã được biên dịch bằng trình biên dịch Pascal của tôi mất 881 chu kỳ xung nhịp và -O2 (mức cao nhất hiện có).
Trình biên dịch Linux Pascal "chính thức" FreePascal không có sẵn bộ đếm chu kỳ xung nhịp, vì vậy tôi chỉ thực thi thời gian ./khóa học
, kết quả là khoảng 0,44 giây, trong đó mã trình biên dịch của tôi là 0,37 giây.
Tôi là một lập trình viên xuất sắc, rất giỏi!