comparison data/fft/FFTDataServer.cpp @ 383:94fc0591ea43 1.2-stable

* merge from trunk (1.2 ended up being tracked from trunk, but we may want this branch for fixes later)
author Chris Cannam
date Wed, 27 Feb 2008 10:32:45 +0000
parents aa8dbac62024
children
comparison
equal deleted inserted replaced
349:f39d33b0b265 383:94fc0591ea43
451 std::cerr << "FFTDataServer::modelAboutToBeDeleted: server is " 451 std::cerr << "FFTDataServer::modelAboutToBeDeleted: server is "
452 << server << std::endl; 452 << server << std::endl;
453 #endif 453 #endif
454 454
455 if (i->second.second > 0) { 455 if (i->second.second > 0) {
456 std::cerr << "ERROR: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName().toStdString() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl; 456 std::cerr << "WARNING: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName().toStdString() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl;
457 return;
457 } 458 }
458 for (ServerQueue::iterator j = m_releasedServers.begin(); 459 for (ServerQueue::iterator j = m_releasedServers.begin();
459 j != m_releasedServers.end(); ++j) { 460 j != m_releasedServers.end(); ++j) {
460 if (*j == server) { 461 if (*j == server) {
461 #ifdef DEBUG_FFT_SERVER 462 #ifdef DEBUG_FFT_SERVER
494 m_fftSize(fftSize), 495 m_fftSize(fftSize),
495 m_polar(polar), 496 m_polar(polar),
496 m_width(0), 497 m_width(0),
497 m_height(0), 498 m_height(0),
498 m_cacheWidth(0), 499 m_cacheWidth(0),
499 m_memoryCache(false), 500 m_cacheWidthPower(0),
500 m_compactCache(false), 501 m_cacheWidthMask(0),
501 m_lastUsedCache(-1), 502 m_lastUsedCache(-1),
503 m_criteria(criteria),
502 m_fftInput(0), 504 m_fftInput(0),
503 m_exiting(false), 505 m_exiting(false),
504 m_suspended(true), //!!! or false? 506 m_suspended(true), //!!! or false?
505 m_fillThread(0) 507 m_fillThread(0)
506 { 508 {
524 size_t maxCacheSize = 20 * 1024 * 1024; 526 size_t maxCacheSize = 20 * 1024 * 1024;
525 size_t columnSize = m_height * sizeof(fftsample) * 2 + sizeof(fftsample); 527 size_t columnSize = m_height * sizeof(fftsample) * 2 + sizeof(fftsample);
526 if (m_width * columnSize < maxCacheSize * 2) m_cacheWidth = m_width; 528 if (m_width * columnSize < maxCacheSize * 2) m_cacheWidth = m_width;
527 else m_cacheWidth = maxCacheSize / columnSize; 529 else m_cacheWidth = maxCacheSize / columnSize;
528 530
531 #ifdef DEBUG_FFT_SERVER
532 std::cerr << "FFTDataServer(" << this << "): cache width nominal "
533 << m_cacheWidth << ", actual ";
534 #endif
535
529 int bits = 0; 536 int bits = 0;
530 while (m_cacheWidth) { m_cacheWidth >>= 1; ++bits; } 537 while (m_cacheWidth > 1) { m_cacheWidth >>= 1; ++bits; }
538 m_cacheWidthPower = bits + 1;
531 m_cacheWidth = 2; 539 m_cacheWidth = 2;
532 while (bits) { m_cacheWidth <<= 1; --bits; } 540 while (bits) { m_cacheWidth <<= 1; --bits; }
533 541 m_cacheWidthMask = m_cacheWidth - 1;
534 if (criteria == StorageAdviser::NoCriteria) { 542
543 #ifdef DEBUG_FFT_SERVER
544 std::cerr << m_cacheWidth << " (power " << m_cacheWidthPower << ", mask "
545 << m_cacheWidthMask << ")" << std::endl;
546 #endif
547
548 if (m_criteria == StorageAdviser::NoCriteria) {
535 549
536 // assume "spectrogram" criteria for polar ffts, and "feature 550 // assume "spectrogram" criteria for polar ffts, and "feature
537 // extraction" criteria for rectangular ones. 551 // extraction" criteria for rectangular ones.
538 552
539 if (m_polar) { 553 if (m_polar) {
540 criteria = StorageAdviser::Criteria 554 m_criteria = StorageAdviser::Criteria
541 (StorageAdviser::SpeedCritical | 555 (StorageAdviser::SpeedCritical |
542 StorageAdviser::LongRetentionLikely); 556 StorageAdviser::LongRetentionLikely);
543 } else { 557 } else {
544 criteria = StorageAdviser::Criteria 558 m_criteria = StorageAdviser::Criteria
545 (StorageAdviser::PrecisionCritical); 559 (StorageAdviser::PrecisionCritical);
546 } 560 }
547 } 561 }
548
549 int cells = m_width * m_height;
550 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb
551 int maximumSize = (cells / 1024) * sizeof(float); // kb
552
553 // We don't have a compact rectangular representation, and compact
554 // of course is never precision-critical
555 bool canCompact = true;
556 if ((criteria & StorageAdviser::PrecisionCritical) || !m_polar) {
557 canCompact = false;
558 minimumSize = maximumSize; // don't use compact
559 }
560
561 StorageAdviser::Recommendation recommendation;
562
563 try {
564
565 recommendation =
566 StorageAdviser::recommend(criteria, minimumSize, maximumSize);
567
568 } catch (InsufficientDiscSpace s) {
569
570 // Delete any unused servers we may have been leaving around
571 // in case we wanted them again
572
573 purgeLimbo(0);
574
575 // This time we don't catch InsufficientDiscSpace -- we
576 // haven't allocated anything yet and can safely let the
577 // exception out to indicate to the caller that we can't
578 // handle it.
579
580 recommendation =
581 StorageAdviser::recommend(criteria, minimumSize, maximumSize);
582 }
583
584 std::cerr << "Recommendation was: " << recommendation << std::endl;
585
586 m_memoryCache = false;
587
588 if ((recommendation & StorageAdviser::UseMemory) ||
589 (recommendation & StorageAdviser::PreferMemory)) {
590 m_memoryCache = true;
591 }
592
593 m_compactCache = canCompact &&
594 (recommendation & StorageAdviser::ConserveSpace);
595
596 std::cerr << "FFTDataServer: memory cache = " << m_memoryCache << ", compact cache = " << m_compactCache << std::endl;
597
598 #ifdef DEBUG_FFT_SERVER
599 std::cerr << "Width " << m_width << ", cache width " << m_cacheWidth << " (size " << m_cacheWidth * columnSize << ")" << std::endl;
600 #endif
601
602 StorageAdviser::notifyPlannedAllocation
603 (m_memoryCache ? StorageAdviser::MemoryAllocation :
604 StorageAdviser::DiscAllocation,
605 m_compactCache ? minimumSize : maximumSize);
606 562
607 for (size_t i = 0; i <= m_width / m_cacheWidth; ++i) { 563 for (size_t i = 0; i <= m_width / m_cacheWidth; ++i) {
608 m_caches.push_back(0); 564 m_caches.push_back(0);
609 } 565 }
610 566
646 602
647 MutexLocker locker(&m_writeMutex, 603 MutexLocker locker(&m_writeMutex,
648 "FFTDataServer::m_writeMutex[~FFTDataServer]"); 604 "FFTDataServer::m_writeMutex[~FFTDataServer]");
649 605
650 for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) { 606 for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) {
607
651 if (*i) { 608 if (*i) {
652 delete *i; 609 delete *i;
653 } else {
654 StorageAdviser::notifyDoneAllocation
655 (m_memoryCache ? StorageAdviser::MemoryAllocation :
656 StorageAdviser::DiscAllocation,
657 m_cacheWidth * m_height *
658 (m_compactCache ? sizeof(uint16_t) : sizeof(float)) / 1024 + 1);
659 } 610 }
660 } 611 }
661 612
662 deleteProcessingData(); 613 deleteProcessingData();
663 } 614 }
722 m_condition.wakeAll(); 673 m_condition.wakeAll();
723 } 674 }
724 } 675 }
725 } 676 }
726 677
678 void
679 FFTDataServer::getStorageAdvice(size_t w, size_t h,
680 bool &memoryCache, bool &compactCache)
681 {
682 int cells = w * h;
683 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb
684 int maximumSize = (cells / 1024) * sizeof(float); // kb
685
686 // We don't have a compact rectangular representation, and compact
687 // of course is never precision-critical
688
689 bool canCompact = true;
690 if ((m_criteria & StorageAdviser::PrecisionCritical) || !m_polar) {
691 canCompact = false;
692 minimumSize = maximumSize; // don't use compact
693 }
694
695 StorageAdviser::Recommendation recommendation;
696
697 try {
698
699 recommendation =
700 StorageAdviser::recommend(m_criteria, minimumSize, maximumSize);
701
702 } catch (InsufficientDiscSpace s) {
703
704 // Delete any unused servers we may have been leaving around
705 // in case we wanted them again
706
707 purgeLimbo(0);
708
709 // This time we don't catch InsufficientDiscSpace -- we
710 // haven't allocated anything yet and can safely let the
711 // exception out to indicate to the caller that we can't
712 // handle it.
713
714 recommendation =
715 StorageAdviser::recommend(m_criteria, minimumSize, maximumSize);
716 }
717
718 std::cerr << "Recommendation was: " << recommendation << std::endl;
719
720 memoryCache = false;
721
722 if ((recommendation & StorageAdviser::UseMemory) ||
723 (recommendation & StorageAdviser::PreferMemory)) {
724 memoryCache = true;
725 }
726
727 compactCache = canCompact &&
728 (recommendation & StorageAdviser::ConserveSpace);
729
730 #ifdef DEBUG_FFT_SERVER
731 std::cerr << "FFTDataServer: memory cache = " << memoryCache << ", compact cache = " << compactCache << std::endl;
732
733 std::cerr << "Width " << w << " of " << m_width << ", height " << h << ", size " << w * h << std::endl;
734 #endif
735 }
736
727 FFTCache * 737 FFTCache *
728 FFTDataServer::getCacheAux(size_t c) 738 FFTDataServer::getCacheAux(size_t c)
729 { 739 {
730 Profiler profiler("FFTDataServer::getCacheAux", false); 740 Profiler profiler("FFTDataServer::getCacheAux", false);
731 #ifdef DEBUG_FFT_SERVER 741 #ifdef DEBUG_FFT_SERVER
782 size_t width = m_cacheWidth; 792 size_t width = m_cacheWidth;
783 if (c * m_cacheWidth + width > m_width) { 793 if (c * m_cacheWidth + width > m_width) {
784 width = m_width - c * m_cacheWidth; 794 width = m_width - c * m_cacheWidth;
785 } 795 }
786 796
797 bool memoryCache = false;
798 bool compactCache = false;
799
800 getStorageAdvice(width, m_height, memoryCache, compactCache);
801
787 try { 802 try {
788 803
789 if (m_memoryCache) { 804 if (memoryCache) {
790 805
791 cache = new FFTMemoryCache 806 cache = new FFTMemoryCache
792 (m_compactCache ? FFTMemoryCache::Compact : 807 (compactCache ? FFTMemoryCache::Compact :
793 // FFTMemoryCache::Polar); 808 m_polar ? FFTMemoryCache::Polar :
794 m_polar ? FFTMemoryCache::Polar : 809 FFTMemoryCache::Rectangular);
795 FFTMemoryCache::Rectangular); 810
796 811 } else {
797 } else if (m_compactCache) {
798 812
799 cache = new FFTFileCache 813 cache = new FFTFileCache
800 (name, 814 (name,
801 MatrixFile::ReadWrite, 815 MatrixFile::ReadWrite,
802 FFTFileCache::Compact); 816 compactCache ? FFTFileCache::Compact :
803 817 m_polar ? FFTFileCache::Polar :
804 } else { 818 FFTFileCache::Rectangular);
805
806 cache = new FFTFileCache
807 (name,
808 MatrixFile::ReadWrite,
809 m_polar ? FFTFileCache::Polar :
810 FFTFileCache::Rectangular);
811 } 819 }
812 820
813 cache->resize(width, m_height); 821 cache->resize(width, m_height);
814 cache->reset(); 822 cache->reset();
815 823
816 } catch (std::bad_alloc) { 824 } catch (std::bad_alloc) {
817 825
818 delete cache; 826 delete cache;
819 cache = 0; 827 cache = 0;
820 828
821 if (m_memoryCache) { 829 if (memoryCache) {
822 830
823 std::cerr << "WARNING: Memory allocation failed when resizing" 831 std::cerr << "WARNING: Memory allocation failed when resizing"
824 << " FFT memory cache no. " << c << " to " << width 832 << " FFT memory cache no. " << c << " to " << width
825 << "x" << m_height << " (of total width " << m_width 833 << "x" << m_height << " (of total width " << m_width
826 << "): falling back to disc cache" << std::endl; 834 << "): falling back to disc cache" << std::endl;
827 835
828 try { 836 try {
829 837
830 cache = new FFTFileCache(name, MatrixFile::ReadWrite, 838 purgeLimbo(0);
839
840 cache = new FFTFileCache(name,
841 MatrixFile::ReadWrite,
831 FFTFileCache::Compact); 842 FFTFileCache::Compact);
832 843
833 cache->resize(width, m_height); 844 cache->resize(width, m_height);
834 cache->reset(); 845 cache->reset();
835 846
852 (0, QApplication::tr("FFT cache resize failed"), 863 (0, QApplication::tr("FFT cache resize failed"),
853 QApplication::tr 864 QApplication::tr
854 ("Failed to create or resize an FFT model slice.\n" 865 ("Failed to create or resize an FFT model slice.\n"
855 "There may be insufficient memory or disc space to continue.")); 866 "There may be insufficient memory or disc space to continue."));
856 } 867 }
857
858 StorageAdviser::notifyDoneAllocation
859 (m_memoryCache ? StorageAdviser::MemoryAllocation :
860 StorageAdviser::DiscAllocation,
861 width * m_height *
862 (m_compactCache ? sizeof(uint16_t) : sizeof(float)) / 1024 + 1);
863 868
864 m_caches[c] = cache; 869 m_caches[c] = cache;
865 m_lastUsedCache = c; 870 m_lastUsedCache = c;
866 return cache; 871 return cache;
867 } 872 }