Apakah 2 ** x lebih cepat untuk dihitung dari exp (x)?

12

Maafkan kenaifan yang akan jelas dalam cara saya mengajukan pertanyaan ini dan juga fakta bahwa saya menanyakannya.

Matematikawan biasanya menggunakan karena itu adalah teori yang paling sederhana / paling baik (karena kalkulus). Tetapi komputer tampaknya melakukan semuanya dalam biner, jadi apakah lebih cepat pada mesin untuk menghitung daripada ?exp2**xMath::exp(x)

isomorfisma
sumber
7
Nomor berapa yang kamu bicarakan? Bilangan bulat berukuran arbiter? Floating point ukuran tetap? Titik mengambang presisi-sewenang-wenang?
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Ini poin bagus. Saya tidak menyadari perbedaan itu penting.
isomorfisma
3
Saya telah melihat pada beberapa kalkulator saku Casio bahwa log dan kekuatan nomor non-e jauh lebih lambat daripada ln / exp
phuclv
2
Untuk mengambil risiko menjadi tumpul, sudahkah Anda mencoba menentukan waktu keduanya dan melihat mana yang lebih cepat? Atau apakah Anda berbicara tentang kecepatan dalam pengertian kompleksitas ? O(f(n))
jmite
1
Bahasa ini bertugas untuk memilih cara tercepat dan akan menghasilkan pekerjaan yang baik. Hanya dalam kasus kecepatan tertinggi diperlukan, dan pengukuran menunjukkan bahwa ini relevan dengan kinerja jika Anda khawatir tentang hal-hal semacam ini
vonbrand

Jawaban:

18

Karena ini adalah CS dan bukan Stackoverflow, saya akan berasumsi bahwa Anda mengajukan pertanyaan tentang analisis numerik, dan (untuk menjaga hal-hal sederhana) khususnya IEEE-754 floating point. Dalam hal itu, jawaban untuk pertanyaan Anda sebagian tergantung pada apa yang Anda maksud dengan "lebih mudah", dan sebagian pada detail sistem.

Tidak ada CPU modern yang saya tahu memiliki instruksi yang dibangun di mana melakukan persis apa yang Anda harapkan baik untuk operasi (yang selanjutnya akan kita sebut , nama yang biasa dalam C) atau 2 x ( ). Keduanya diimplementasikan menggunakan fungsi perpustakaan.exexp2xexp2

Seperti halnya semua metode numerik untuk operasi transendental, ada beberapa kasus khusus yang perlu dipertimbangkan:

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

Namun, ada hal lain yang membuat masalah sedikit lebih rumit: domain yang berguna cukup kecil. Untuk binary32, exp(x)underflow jika atau lebih, dan overflow jika x > 88,7 atau lebih. Tidak seperti biasanya untuk operasi transendental, kita juga dapat mengabaikan kasus subnormal, karena tidak dapat dibedakan dari apakah subnormal. Semua hal di atas juga berlaku untuk , kecuali bahwa domainnya sedikit berbeda.x<104x>88.7exp(x)1.0xexp2

ex=2x/ln21ln2exp2K

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

nxT2j/Kj[0,K)P2x[0,1K)2nTP

f2xm12x1x[1,1]

Meskipun x87 mendukung instruksi transendental, implementasi pustaka perangkat lunak dari fungsi transendental dapat lebih cepat dalam banyak kasus.

Sunting: Sudah ditunjukkan dalam komentar bahwa saya harus menjelaskan beberapa terminologi baru yang digunakan dalam IEEE 754-2008. Beberapa bahasanya telah berubah sejak 1985 dan 1987, dan kebanyakan orang jauh lebih akrab dengan jargon lama.

Istilah "binary32" dan "binary64" adalah nama baru untuk angka floating-point biner 32-bit dan 64-bit, yang standar lama masing-masing disebut "tunggal" dan "ganda".

Istilah "nomor subnormal" menggantikan istilah "nomor dinormal" atau "nomor dinormalisasi" sebelumnya .

Nama samaran
sumber
ketika Anda mengatakan "subnormal" - Anda jelas tidak bermaksud "sub-Gaussian"; maksud Anda "lebih buruk dari [tolok ukur khas]"?
isomorfisma
2
@isomorphismes Di sini, 'subnormal' berkenaan dengan bagaimana mengapung diimplementasikan. Lihat nomor tidak normal di Wikipedia.
Paul Manta
Kebetulan, saya terlalu menyederhanakan "metode khas" hanya sedikit. Dimungkinkan untuk mengimplementasikan exp2 () dan exp () dengan akurasi ulp hanya menggunakan satu ekstensi kecil (dan cukup mudah dimengerti) untuk metode yang disajikan di sini, tetapi penjelasan tentang ekstensi kecil yang mudah dipahami mungkin akan menggandakan panjang jawabannya!
Nama samaran
6

2**x2x<<1 << x

kepala kebun
sumber
4
sebenarnya tidak. x mungkin tipe floating-point
phuclv
1
x
Jika xbukan bilangan bulat (katakanlah, 20.75), Anda akan mengatur mantissa ke 2dan eksponen ke nilai bulat xsebagai estimasi paling akurat (representasi tepat tidak mungkin). Yang juga jauh lebih cepat daripada `pow '.
Damon
1

Jika 2**xfungsi pada bilangan bulat, maka saya setuju dengan jawaban Stephen, pergeseran lebih murah. Tapi saya biasanya melihat itu sebagai 2^xdan **untuk menunjukkan exponentiation floating point. Untuk kasus ini, saya mengharapkan kinerja yang sama antara **dan ^karena keduanya expdan pow(operasi yang mendasari **) keduanya operasi perkiraan transendental.

Tim
sumber
Menarik, saya tidak tahu **dianggap sinonim untuk versi floating-point (dan, konyol saya, saya lupa keduanya akan berbeda).
isomorfisma
1

Karena 2 ^ x = e ^ (x * ln 2) dan e ^ x = 2 ^ (x * log2 (e)), Anda tidak akan mengharapkan banyak perbedaan.

Untuk x mendekati nol, orang biasanya akan menggunakan polinomial e ^ x = 1 + x + x ^ 2/2 + x ^ 3/6 ..., dioptimalkan dengan baik untuk memotong sesegera mungkin sambil menjaga kesalahan pembulatan kecil . Jelas 2 ^ x adalah, kecil sedikit lebih lambat untuk menghitung. "x close to 0" biasanya berupa nilai x di mana sqrt (1/2) <= e ^ x <= sqrt (2). Membatasi rentang x memastikan bahwa derajat polinom tidak perlu dipilih terlalu tinggi.

Untuk x yang lebih besar, seseorang biasanya menghitung 2 ^ x dengan membiarkan x = x '+ x' ', di mana x' adalah bilangan bulat dan -0,5 <= x '' <= 0,5. 2 ^ x 'kemudian akan dihitung dengan membangun angka floating point dengan pola bit yang tepat, dan 2 ^ x' 'dengan menggunakan metode e ^ x untuk x kecil. Di sini, 2 ^ x sedikit lebih cepat. Selain itu, jika x lebih besar (katakanlah x = 100,3), hanya mengalikan x dengan log2 (e) akan menimbulkan kesalahan pembulatan yang tidak dapat diterima (karena ada lebih sedikit bit fraksional), sehingga lebih banyak perhatian harus diambil.

Dan mudah-mudahan fungsi perpustakaan yang baik akan berhati-hati bahwa setiap kali x <= y, e ^ x <= e ^ y dan 2 ^ x <= 2 ^ y, tidak peduli apa kesalahan pembulatannya. Mencapai hal semacam itu bisa rumit.

gnasher729
sumber
0

Anda harus memahami bahwa matematika di komputer dilakukan dengan cara yang berbeda oleh perangkat lunak yang berbeda, semoga muncul dengan jawaban yang konsisten. Melihat sebagian besar perangkat lunak, saya pikir komputer berperilaku seperti komputer - baik dan akan menghitung jawabannya jauh bahkan untuk seperti 0 ^ 0. Masalahnya adalah bahwa kasus khusus melibatkan "pengakuan" yang tidak terjadi secara gratis di komputer digital. Ini berarti bahwa hanya dalam kasus-kasus di mana memiliki jawaban akan mempercepat "yang paling" akan optimasi terjadi. Tetapi dalam kasus-kasus itu akan terjadi dengan sangat baik. Perhatikan juga bahwa beberapa pengakuan berbeda mungkin harus dilakukan untuk mendapatkan jawaban yang benar. Ini disebut tingkat optimisasi kecepatan dan ini telah terjadi hingga tingkat profesional maksimum berdasarkan sebagian besar perangkat lunak yang disebut GNU "C". Ini karena di sini perbedaan menit dalam menjalankan waktu dari perangkat lunak ke perangkat lunak dan mesin ke mesin digunakan di sana sebagai angka penerimaan kualitas. Pada penerjemah lain biasanya hanya jika "bendera nol" terjadi sebagai efek samping dari perhitungan sebelumnya akan mempercepat pengenalan dilakukan. seperti 0 * x => C0.

Menandai
sumber