Là 2 ** x để tính toán nhanh hơn exp (x)?


12

Tha thứ cho sự ngây thơ sẽ rõ ràng trong cách tôi hỏi câu hỏi này cũng như thực tế là tôi đang hỏi nó.

Các nhà toán học thường sử dụng exp vì đây là cơ sở đơn giản / đẹp nhất trong lý thuyết (do tính toán). Nhưng máy tính dường như làm mọi thứ trong hệ nhị phân, vậy máy tính có nhanh 2**xhơn Math::exp(x)không?


7
Bạn đang nói về loại số nào? Số nguyên có kích thước tùy ý? Điểm nổi có kích thước cố định? Điểm nổi chính xác tùy ý?
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Đó là một điểm tốt. Tôi đã không nhận ra sự khác biệt là quan trọng.
đẳng cấu

3
Tôi đã thấy trên một số máy tính bỏ túi Casio ghi nhật ký và sức mạnh của số không phải e chậm hơn nhiều so với ln / exp
phuclv

2
Để có nguy cơ bị cùn, bạn đã thử định thời gian cho cả hai và xem cái nào nhanh hơn chưa? Hay bạn đang nói về tốc độ theo nghĩa phức tạp ? O(f(n))
jmite

1
Ngôn ngữ có trách nhiệm chọn cách nhanh nhất và sẽ làm tốt công việc đó. Chỉ trong trường hợp tốc độ tối đa là bắt buộc và các phép đo đã chỉ ra rằng điều này có liên quan đến hiệu suất nếu bạn lo lắng về loại công cụ này
vonbrand

Câu trả lời:


18

Vì đây là CS chứ không phải Stackoverflow, tôi sẽ giả định rằng bạn đang đặt câu hỏi về phân tích số và đặc biệt là (để giữ cho mọi thứ đơn giản) điểm nổi của IEEE-754. Trong trường hợp đó, câu trả lời cho câu hỏi của bạn một phần phụ thuộc vào ý của bạn là "dễ dàng hơn" và một phần dựa trên các chi tiết của hệ thống.

Không có CPU hiện đại nào tôi biết có một lệnh được xây dựng trong đó thực hiện chính xác những gì bạn mong đợi cho hoạt động (mà từ đó chúng ta sẽ gọi , tên thông thường của nó là C) hoặc 2 x ( ). Cả hai đều được thực hiện bằng cách sử dụng các chức năng thư viện.exexp2xexp2

Như trường hợp của tất cả các phương thức số cho các hoạt động siêu việt, có một vài trường hợp đặc biệt cần xem xét:

exp(NaN) = NaN
exp(+Inf) = +Inf
exp(-Inf) = 0

Tuy nhiên, có một điều khác làm cho vấn đề hơi phức tạp hơn một chút: miền hữu ích khá nhỏ. Đối với binary32, exp(x)tràn xuống nếu trở lên và tràn ra nếu x > 88,7 trở lên. Bất thường cho các hoạt động siêu việt, chúng ta cũng có thể bỏ qua trường hợp không bình thường, vì không thể phân biệt được nếu là không bình thường. Tất cả những điều trên cũng đúng , ngoại trừ tên miền hơi khác một chút.x<104x>88.7exp(x)1.0xexp2

Trực giác của bạn là đúng trong đó hầu hết các triển khai đều tính toán . Tuy nhiên, chi phí của phép nhân đó bằng 1ex=2x/ln2 là tầm thường so với phần còn lại của máy tính. Một phương thức điển hình sử dụng bảng được tính toán trước vớicác phần tửK:1ln2exp2K

exp2(x)=2n×T[j]×P(y)

Trong đó là phần nguyên của x , bảng T chứa các giá trị 2 j / K cho tất cả j trong phạm vi [ 0 , K )P là một số xấp xỉ đa thức đến 2 x (tứ phân là đủ cho nhị phân32) trong phạm vi [ 0 , 1nxT2j/Kj[0,K)P2x. Phần2nlà rẻ, vì nó chỉ thao túng số mũ. Tlà một bảng tra cứu. Vì vậy,Pcó thể là phần đắt tiền của hoạt động.[0,1K)2nTP

Tôi nên chỉ ra sự hoàn chỉnh rằng Intel x86 FPU bao gồm một lệnh được gọi f2xm1, tính toán cho x trong phạm vi [ - 1 , 1 ] . Tuy nhiên, trên một CPU hiện đại, đây là một hướng dẫn khá tốn kém và không có đường ống, và bạn rất nản lòng khi sử dụng nó. Như Hướng dẫn Tham khảo Tối ưu hóa Intel Phần 3.8.5 ghi chú đúng:2x1x[1,1]

Mặc dù x87 hỗ trợ các hướng dẫn siêu việt, việc triển khai thư viện phần mềm của chức năng siêu việt có thể nhanh hơn trong nhiều trường hợp.

Chỉnh sửa: Nó đã được chỉ ra trong các ý kiến ​​rằng tôi nên giải thích một số thuật ngữ mới được sử dụng trong IEEE 754-2008. Một số ngôn ngữ đã thay đổi từ năm 1985 và 1987, và hầu hết mọi người đã quen thuộc hơn nhiều với biệt ngữ cũ.

Các thuật ngữ "binary32" và "binary64" là tên mới của các số dấu phẩy động nhị phân 32 bit và 64 bit, mà tiêu chuẩn cũ gọi là "đơn" và "kép" tương ứng.

Thuật ngữ "số không bình thường" thay thế cho thuật ngữ "số không bình thường" trước đó hoặc "số không chuẩn hóa" .


khi bạn nói "không bình thường" - bạn rõ ràng không có nghĩa là "tiểu Gaussian"; bạn có nghĩa là "tồi tệ hơn [một số điểm chuẩn của tính điển hình]"?
đẳng cấu

2
@isomorphismes Ở đây, 'không bình thường' liên quan đến cách thức thực hiện phao. Xem các số bất thường trên Wikipedia.
Paul Manta

Ngẫu nhiên, tôi đã quá đơn giản hóa "phương pháp điển hình" chỉ một chút. Có thể triển khai exp2 () và exp () với độ chính xác ulp chỉ bằng một phần mở rộng nhỏ (và khá dễ hiểu) cho phương pháp được trình bày ở đây, nhưng một lời giải thích về phần mở rộng nhỏ dễ hiểu có thể sẽ tăng gấp đôi độ dài câu trả lời!
Bút danh

6

Nếu 2**xbạn có nghĩa là , thì có. Chúng ta có thể sử dụng toán tử shift trái , tức là chúng ta tính toán . Điều này nhanh như chớp vì nó là một hướng dẫn máy nguyên thủy trong mọi bộ xử lý mà tôi biết. Điều này không thể được thực hiện với bất kỳ cơ sở nào ngoài 2. Ngoài ra, lũy thừa số nguyên sẽ luôn nhanh hơn lũy thừa thực, vì các số dấu phẩy động mất nhiều thời gian hơn để nhân lên.2x<<1 << x


4
không thực sự x có thể là loại dấu phẩy động
phuclv

1
x

Nếu xkhông phải là số nguyên (giả sử 20.75), bạn sẽ đặt giá trị thành 2và số mũ thành giá trị làm tròn xlà ước tính chính xác nhất (không thể biểu diễn chính xác). Cái nào cũng vậy, nhanh hơn nhiều so với `pow.
Damon

1

Nếu 2**xlà một hàm trên số nguyên, thì tôi đồng ý với câu trả lời của Stephen, sự thay đổi rẻ hơn. Nhưng tôi thường thấy rằng như 2^x**để chỉ ra lũy thừa điểm nổi. Trong trường hợp này, tôi mong đợi hiệu suất tương tự giữa **^vì cả hai exppow(hoạt động cơ bản cho **) đều là các hoạt động gần đúng siêu việt.


Thật thú vị, tôi không biết **được coi là một từ đồng nghĩa với phiên bản dấu phẩy động (và, thật ngốc, tôi đã quên hai cái sẽ khác nhau).
đẳng cấu

1

Vì 2 ^ x = e ^ (x * ln 2) và e ^ x = 2 ^ (x * log2 (e)), bạn sẽ không mong đợi nhiều sự khác biệt.

Đối với x gần bằng 0, người ta thường sử dụng đa thức e ^ x = 1 + x + x ^ 2/2 + x ^ 3/6 ..., được tối ưu hóa tốt nhất để cắt càng sớm càng tốt trong khi vẫn giữ sai số làm tròn nhỏ . Rõ ràng 2 ^ x là một tính toán nhỏ, chậm một chút để tính toán. "x gần 0" thường sẽ là các giá trị của x trong đó sqrt (1/2) <= e ^ x <= sqrt (2). Hạn chế phạm vi của x đảm bảo rằng mức độ đa thức không cần phải được chọn quá cao.

Đối với x lớn hơn, người ta thường sẽ tính 2 ^ x bằng cách cho x = x '+ x' ', trong đó x' là một số nguyên và -0,5 <= x '' <= 0,5. 2 ^ x 'sau đó sẽ được tính bằng cách xây dựng một số dấu phẩy động với mẫu bit bên phải và 2 ^ x' 'bằng cách sử dụng phương thức e ^ x cho x nhỏ. Ở đây, 2 ^ x nhanh hơn một chút. Hơn nữa, nếu x là lớn (giả sử x = 100.3), chỉ cần nhân x với log2 (e) sẽ gây ra lỗi làm tròn không thể chấp nhận (vì có nhiều bit phân đoạn ít hơn), do đó cần phải cẩn thận hơn.

Và hy vọng rằng một hàm thư viện tốt sẽ đảm bảo rằng bất cứ khi nào x <= y, e ^ x <= e ^ y và 2 ^ x <= 2 ^ y, bất kể lỗi làm tròn là gì. Đạt được điều đó có thể là khó khăn.


0

Bạn đã hiểu rằng toán học trên máy tính được thực hiện theo nhiều cách khác nhau bằng các phần mềm khác nhau, hy vọng sẽ đưa ra các câu trả lời nhất quán. Nhìn vào hầu hết các phần mềm, tôi nghĩ rằng máy tính hoạt động tốt - máy tính và sẽ tính toán câu trả lời trong khoảng thời gian dài ngay cả với giá trị 0 ^ 0. Vấn đề là các trường hợp đặc biệt liên quan đến "sự công nhận" không xảy ra miễn phí trong các máy tính kỹ thuật số. Điều này có nghĩa là chỉ trong những trường hợp có câu trả lời sẽ tăng tốc mọi thứ "tối đa" mới xảy ra. Nhưng trong những trường hợp đó nó sẽ xảy ra cực kỳ tốt. Cũng lưu ý rằng một số nhận dạng khác nhau có thể phải được thực hiện để có câu trả lời đúng. Đây được gọi là mức tối ưu hóa tốc độ và điều này đã xảy ra ở mức độ chuyên nghiệp tối đa trên cơ sở hầu hết các phần mềm được gọi là GNU "C". Điều này là do ở đây có sự khác biệt nhỏ về thời gian chạy từ phần mềm đến phần mềm và máy này sang máy khác được sử dụng ở đó làm số liệu chấp nhận chất lượng. Trong các thông dịch viên khác thường chỉ khi "cờ không" xảy ra do tác dụng phụ của các tính toán trước đó sẽ tăng tốc độ nhận dạng được thực hiện. chẳng hạn như 0 * x => C0.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.