Tôi có một mã số giải phương trình f(x) = 0
, trong đó tôi phải tăng x
lên một điện p
. Tôi giải quyết nó bằng cách sử dụng một loạt các thứ, nhưng cuối cùng tôi có phương pháp của Newton. Giải pháp này xảy ra bằng x = 1
và do đó là nguyên nhân của sự cố của tôi. Khi giải pháp được lặp lại gần với 1
, giả sử x = 1 + 1e-13
, thời gian cần thiết để tính toán std::pow(x, p)
tăng lên rất nhiều, dễ dàng với hệ số 100, làm cho mã của tôi không sử dụng được.Rất chậm std :: pow() cho các căn cứ rất gần với 1
Máy chạy điều này là AMD64 (Opteron 6172) trên CentOS và lệnh đơn giản là . Hành vi tương tự xuất hiện trên tất cả các máy của tôi, tất cả x64. Theo tài liệu here, đây không chỉ là vấn đề của tôi (tức là, người khác cũng đang tức giận), chỉ xuất hiện trên x64 và chỉ cho x
gần với 1.0
. Điều tương tự cũng xảy ra với exp
.
Giải quyết vấn đề này là rất quan trọng đối với tôi. Có ai biết nếu có bất kỳ cách nào để đi xung quanh sự chậm chạp này?
EDIT: John đã chỉ ra rằng điều này là do các biến thể. Câu hỏi là sau đó, làm thế nào để sửa lỗi này? Mã này là C++, được biên dịch với g++
để sử dụng trong phạm vi GNU Octave
. Dường như, mặc dù tôi đã đặt CXXFLAGS
để bao gồm -mtune=native
và -ffast-math
, điều đó không giúp ích và mã chạy chậm.
PSEUDO-GIẢI PHÁP NGAY BÂY GIỜ: Đối với tất cả những ai quan tâm đến vấn đề này, các giải pháp được đề xuất bên dưới không hiệu quả đối với cá nhân tôi. Tôi thực sự cần tốc độ thông thường là std::pow()
, nhưng không có sự chậm chạp xung quanh x = 1
. Các giải pháp cho cá nhân tôi là sử dụng hack như sau:
inline double mpow(double x, double p) __attribute__ ((const));
inline double mpow(double x, double p)
{
double y(x - 1.0);
return (std::abs(y) > 1e-4) ? (std::pow(x, p)) : (1.0 + p * y * (1.0 + (p - 1.0) * y * (0.5 + (1.0/6.0) * (p - 2.0) * y)));
}
các ràng buộc có thể thay đổi, nhưng đối với -40 < p < 40 lỗi là nhỏ hơn khoảng 1e-11, đó là đủ tốt. Overhead là tối thiểu từ những gì tôi tìm thấy, do đó giải quyết vấn đề cho tôi.
này có thể liên quan đến các vấn đề hiệu suất chung với [số subnormal] (http://en.wikipedia.org/wiki/Denormal_number). Tính toán với các giá trị dấu phẩy động rất gần với 0 có thể chậm hơn 100 lần so với bình thường. Xem http://stackoverflow.com/questions/9314534/why-does-changing-0-1f-to-0-slow-down-performance-by-10x. –
Điểm tốt. Bất kỳ gợi ý nào về cách giải quyết vấn đề này? Sửa các con số chính xác 1 nếu chúng đủ gần? –
@JohnKugelman: Nếu bạn đọc liên kết, điều này là do glibc sử dụng hàm chậm hơn nhiều (có tên '__slowpow') khi được cung cấp một số giá trị đầu vào nhất định. – interjay