Hiệu quả 10 lên gấp đôi sức mạnh
Tôi phải nâng số 10 lên gấp đôi rất nhiều lần.
Có cách nào hiệu quả hơn để làm điều này ngoài thư viện toán học pow(10,double)không? Nếu nó quan trọng, số tiền đôi của tôi luôn âm từ -5 đến -11.
Tôi giả sử pow (double, double) sử dụng một thuật toán tổng quát hơn là bắt buộc đối với pow (10, double) và do đó có thể không phải là phương pháp nhanh nhất. Đưa ra một số câu trả lời dưới đây, đó có thể là một giả định không chính xác.
Đối với lý do tại sao, nó là cho nội suy logartihmic. Tôi có một bảng giá trị x và y. Đối tượng của tôi có một giá trị x đã biết (hầu như luôn luôn là một đôi).
double Dbeta(struct Data *diffusion, double per){
double frac;
while(per>diffusion->x[i]){
i++;
}
frac = (per-diffusion->x[i-1])/(diffusion->x[i]-diffusion->x[i-1]);
return pow(10,log10DB[i-1] + frac * (log10DB[i]-log10DB[i-1]));
}
Chức năng này được gọi rất nhiều lần. Tôi đã được yêu cầu xem xét hồ sơ, vì vậy đó là những gì tôi sẽ làm đầu tiên.
Tôi vừa được thông báo rằng tôi có thể đã sử dụng logarit tự nhiên thay vì cơ số 10, điều này rõ ràng là đúng. (sự ngu ngốc của tôi đôi khi khiến cả bản thân tôi kinh ngạc.)
Sau khi thay thế mọi thứ bằng logarit tự nhiên, mọi thứ chạy nhanh hơn một chút. Với việc lập hồ sơ (là một từ mới mà tôi đã học ngày hôm nay), tôi phát hiện ra 39% mã của tôi được sử dụng trong hàm exp, vì vậy đối với những người tự hỏi liệu có phải phần này đang làm tắc nghẽn mã của tôi hay không.
Trả lời
Có, chức năng pow chậm (khoảng 50 lần chi phí của một phép nhân, đối với những người yêu cầu điểm chuẩn).
Bằng một số thủ thuật log / exponents, chúng ta có thể biểu thị 10 ^ x là
10^x = exp(log(10^x)) = exp(x * log(10)).Vì vậy, bạn có thể triển khai 10 ^ x với
exp(x * M_LN10), sẽ hiệu quả hơn pow.Nếu độ chính xác kép không quan trọng, hãy sử dụng phiên bản float của hàm
expf(hoặcpowf), sẽ hiệu quả hơn phiên bản kép.Nếu độ chính xác thô là Ok, hãy tính toán trước một bảng trong phạm vi [-5, -11] và tra cứu nhanh bằng nội suy tuyến tính.
Một số điểm chuẩn (sử dụng glibc 2.31):
Benchmark Time
---------------------------------
pow(10, x) 15.54 ns
powf(10, x) 7.18 ns
expf(x * (float)M_LN10) 3.45 ns
Vì pow(10.0, n)nó sẽ nhanh hơn để thiết lập c = log(10.0), bạn có thể tính toán một lần, sau đó sử dụng exp(c*n), sẽ nhanh hơn đáng kể pow(10.0, n)(về cơ bản là thực hiện điều tương tự trong nội bộ, ngoại trừ nó sẽ được tính toán log(10.0)nhiều lần thay vì chỉ một lần). Ngoài ra, có lẽ bạn không thể làm được gì khác.