|
344 | 344 |
|
345 | 345 | ;; ### Testing Thread Performance |
346 | 346 |
|
347 | | -;; Let's test with power-of-2 sizes to ensure we're using the fast Cooley-Tukey algorithm. |
| 347 | +;; Let's test with power-of-2 sizes to ensure we're using the fast SPLIT_RADIX plan. |
348 | 348 | ;; We'll use [criterium](https://github.com/hugoduncan/criterium) for proper JVM benchmarking (warmup, statistics, GC handling): |
349 | 349 |
|
350 | 350 | (import 'pl.edu.icm.jlargearrays.ConcurrencyUtils |
|
431 | 431 |
|
432 | 432 | ;; Based on our experiments: **Don't worry about thread count for 1D FFT**. Use the default (typically matching your CPU cores), or even just 1 thread. The performance difference is negligible for typical signal sizes, and single-threaded is more predictable. |
433 | 433 | ;; |
434 | | -;; If you need maximum performance, focus on: |
435 | | -;; - Using power-of-2 signal sizes (triggers fast Cooley-Tukey algorithm) |
436 | | -;; - Choosing the right library (JTransforms/fastmath are fastest) |
| 434 | +;; If you need good performance, focus on: |
| 435 | +;; - Using power-of-2 signal sizes (triggers fast SPLIT_RADIX plan) |
| 436 | +;; - Choosing an appropriate library (JTransforms/fastmath are typically fastest for 1D, though differences aren't huge) |
437 | 437 | ;; - Optimizing your overall algorithm to minimize FFT calls |
438 | 438 |
|
439 | 439 | ;; **Note:** 2D and 3D FFTs may benefit more from parallelization since they have more work to distribute. We only tested 1D here. |
|
526 | 526 |
|
527 | 527 | ;; **For most Clojure projects: fastmath 3** |
528 | 528 | ;; |
529 | | -;; fastmath provides the best balance of performance and developer experience: |
| 529 | +;; fastmath provides a good balance of performance and developer experience: |
530 | 530 | ;; - Idiomatic Clojure API (functional, immutable) |
531 | | -;; - Leverages JTransforms' parallelized performance |
| 531 | +;; - Leverages JTransforms' performance |
532 | 532 | ;; - Rich ecosystem (transforms, signal processing, statistics) |
533 | 533 | ;; - Actively maintained |
534 | 534 | ;; |
|
539 | 539 | (let [fft (fm-transform/transformer :real :fft)] |
540 | 540 | (-> signal |
541 | 541 | (fm-transform/forward-1d fft) |
542 | | - (fm-transform/reverse-1d fft)))) ; Round-trip |
| 542 | + (fm-transform/reverse-1d fft)))) |
543 | 543 |
|
544 | | -;; **For maximum performance: JTransforms (directly)** |
| 544 | +;; **For direct Java interop: JTransforms** |
545 | 545 | ;; |
546 | | -;; If you need the absolute fastest FFT and don't mind mutation: |
| 546 | +;; If you want to use JTransforms directly and don't mind mutation: |
547 | 547 | ;; - Use `DoubleFFT_1D` directly |
548 | 548 | ;; - In-place mutations avoid allocations |
549 | | -;; - Parallelized algorithms scale well |
550 | | -;; - Good for real-time audio processing or large-scale data |
| 549 | +;; - May be slightly faster than fastmath wrapper in some cases |
| 550 | +;; - Good for real-time audio processing or when you need fine-grained control |
551 | 551 |
|
552 | 552 | ;; **For broader DSP needs: JDSP** |
553 | 553 | ;; |
554 | 554 | ;; If you need filters, wavelets, peak detection, and FFT in one package: |
555 | 555 | ;; - Convenient, batteries-included library |
556 | 556 | ;; - Simple API |
557 | 557 | ;; - Good documentation |
558 | | -;; - Note: FFT performance lags behind JTransforms |
| 558 | +;; - Note: FFT performance is somewhat slower than JTransforms/fastmath |
559 | 559 |
|
560 | | -;; **Avoid: Apache Commons Math (for FFT specifically)** |
| 560 | +;; **Apache Commons Math: Consider alternatives** |
561 | 561 | ;; |
562 | | -;; While Commons Math is excellent for general mathematics, for FFT specifically: |
563 | | -;; - Slower than JTransforms |
| 562 | +;; While Commons Math is excellent for general mathematics, for FFT specifically you might prefer other options: |
| 563 | +;; - Somewhat slower than JTransforms/fastmath |
564 | 564 | ;; - Returns boxed `Complex[]` objects (allocation overhead) |
565 | | -;; - Consider it if you're already using Commons Math for other features |
| 565 | +;; - Still a reasonable choice if you're already using Commons Math for other features |
566 | 566 |
|
567 | 567 | ;; ## Summary |
568 | 568 |
|
569 | | -;; The Clojure ecosystem offers excellent FFT options through Java interop. For typical signal processing tasks, **fastmath 3** provides the sweet spot: JTransforms' performance wrapped in a Clojure-friendly API. For the ultimate speed, use **JTransforms directly**. And if you need comprehensive DSP utilities beyond FFT, **JDSP** is worth exploring. |
570 | | -;; |
571 | | -;; All code from this comparison is available in the [Clojure Civitas repository](https://github.com/clojurecivitas/clojurecivitas.github.io). |
| 569 | +;; The Clojure ecosystem offers several good FFT options through Java interop. For typical signal processing tasks, **fastmath 3** is a solid choice: JTransforms' performance wrapped in a Clojure-friendly API. For direct control, use **JTransforms directly**. And if you need comprehensive DSP utilities beyond FFT, **JDSP** is worth exploring. |
0 commit comments