Mercurial > hg > svcore
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 } |