Mercurial > hg > svcore
comparison data/fft/FFTMemoryCache.cpp @ 537:3cc4b7cd2aa5
* Merge from one-fftdataserver-per-fftmodel branch. This bit of
reworking (which is not described very accurately by the title of
the branch) turns the MatrixFile object into something that either
reads or writes, but not both, and separates the FFT file cache
reader and writer implementations separately. This allows the
FFT data server to have a single thread owning writers and one reader
per "customer" thread, and for all locking to be vastly simplified
and concentrated in the data server alone (because none of the
classes it makes use of is used in more than one thread at a time).
The result is faster and more trustworthy code.
author | Chris Cannam |
---|---|
date | Tue, 27 Jan 2009 13:25:10 +0000 |
parents | 115f60df1e4d |
children | 1469caaa8e67 |
comparison
equal
deleted
inserted
replaced
536:beb51f558e9c | 537:3cc4b7cd2aa5 |
---|---|
15 | 15 |
16 #include "FFTMemoryCache.h" | 16 #include "FFTMemoryCache.h" |
17 #include "system/System.h" | 17 #include "system/System.h" |
18 | 18 |
19 #include <iostream> | 19 #include <iostream> |
20 #include <cstdlib> | |
20 | 21 |
21 //#define DEBUG_FFT_MEMORY_CACHE 1 | 22 //#define DEBUG_FFT_MEMORY_CACHE 1 |
22 | 23 |
23 FFTMemoryCache::FFTMemoryCache(StorageType storageType) : | 24 FFTMemoryCache::FFTMemoryCache(FFTCache::StorageType storageType, |
24 m_width(0), | 25 size_t width, size_t height) : |
25 m_height(0), | 26 m_width(width), |
27 m_height(height), | |
26 m_magnitude(0), | 28 m_magnitude(0), |
27 m_phase(0), | 29 m_phase(0), |
28 m_fmagnitude(0), | 30 m_fmagnitude(0), |
29 m_fphase(0), | 31 m_fphase(0), |
30 m_freal(0), | 32 m_freal(0), |
32 m_factor(0), | 34 m_factor(0), |
33 m_storageType(storageType) | 35 m_storageType(storageType) |
34 { | 36 { |
35 #ifdef DEBUG_FFT_MEMORY_CACHE | 37 #ifdef DEBUG_FFT_MEMORY_CACHE |
36 std::cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type " | 38 std::cerr << "FFTMemoryCache[" << this << "]::FFTMemoryCache (type " |
37 << m_storageType << ")" << std::endl; | 39 << m_storageType << "), size " << m_width << "x" << m_height << std::endl; |
38 #endif | 40 #endif |
41 | |
42 initialise(); | |
39 } | 43 } |
40 | 44 |
41 FFTMemoryCache::~FFTMemoryCache() | 45 FFTMemoryCache::~FFTMemoryCache() |
42 { | 46 { |
43 #ifdef DEBUG_FFT_MEMORY_CACHE | 47 #ifdef DEBUG_FFT_MEMORY_CACHE |
61 if (m_fimag) free(m_fimag); | 65 if (m_fimag) free(m_fimag); |
62 if (m_factor) free(m_factor); | 66 if (m_factor) free(m_factor); |
63 } | 67 } |
64 | 68 |
65 void | 69 void |
66 FFTMemoryCache::resize(size_t width, size_t height) | 70 FFTMemoryCache::initialise() |
67 { | 71 { |
68 Profiler profiler("FFTMemoryCache::resize"); | 72 Profiler profiler("FFTMemoryCache::initialise"); |
69 | 73 |
70 #ifdef DEBUG_FFT_MEMORY_CACHE | 74 size_t width = m_width, height = m_height; |
71 std::cerr << "FFTMemoryCache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl; | 75 |
72 #endif | 76 #ifdef DEBUG_FFT_MEMORY_CACHE |
73 | 77 std::cerr << "FFTMemoryCache[" << this << "]::initialise(" << width << "x" << height << " = " << width*height << ")" << std::endl; |
74 if (m_width == width && m_height == height) return; | 78 #endif |
75 | 79 |
76 if (m_storageType == Compact) { | 80 if (m_storageType == FFTCache::Compact) { |
77 resize(m_magnitude, width, height); | 81 initialise(m_magnitude); |
78 resize(m_phase, width, height); | 82 initialise(m_phase); |
79 } else if (m_storageType == Polar) { | 83 } else if (m_storageType == FFTCache::Polar) { |
80 resize(m_fmagnitude, width, height); | 84 initialise(m_fmagnitude); |
81 resize(m_fphase, width, height); | 85 initialise(m_fphase); |
82 } else { | 86 } else { |
83 resize(m_freal, width, height); | 87 initialise(m_freal); |
84 resize(m_fimag, width, height); | 88 initialise(m_fimag); |
85 } | 89 } |
86 | 90 |
87 m_colset.resize(width); | 91 m_colset.resize(width); |
88 | 92 |
89 m_factor = (float *)realloc(m_factor, width * sizeof(float)); | 93 m_factor = (float *)realloc(m_factor, width * sizeof(float)); |
95 std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl; | 99 std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl; |
96 #endif | 100 #endif |
97 } | 101 } |
98 | 102 |
99 void | 103 void |
100 FFTMemoryCache::resize(uint16_t **&array, size_t width, size_t height) | 104 FFTMemoryCache::initialise(uint16_t **&array) |
101 { | 105 { |
102 for (size_t i = width; i < m_width; ++i) { | 106 array = (uint16_t **)malloc(m_width * sizeof(uint16_t *)); |
103 free(array[i]); | 107 if (!array) throw std::bad_alloc(); |
104 } | 108 MUNLOCK(array, m_width * sizeof(uint16_t *)); |
105 | 109 |
106 if (width != m_width) { | 110 for (size_t i = 0; i < m_width; ++i) { |
107 array = (uint16_t **)realloc(array, width * sizeof(uint16_t *)); | 111 array[i] = (uint16_t *)malloc(m_height * sizeof(uint16_t)); |
108 if (!array) throw std::bad_alloc(); | |
109 MUNLOCK(array, width * sizeof(uint16_t *)); | |
110 } | |
111 | |
112 for (size_t i = m_width; i < width; ++i) { | |
113 array[i] = 0; | |
114 } | |
115 | |
116 for (size_t i = 0; i < width; ++i) { | |
117 array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t)); | |
118 if (!array[i]) throw std::bad_alloc(); | 112 if (!array[i]) throw std::bad_alloc(); |
119 MUNLOCK(array[i], height * sizeof(uint16_t)); | 113 MUNLOCK(array[i], m_height * sizeof(uint16_t)); |
120 } | 114 } |
121 } | 115 } |
122 | 116 |
123 void | 117 void |
124 FFTMemoryCache::resize(float **&array, size_t width, size_t height) | 118 FFTMemoryCache::initialise(float **&array) |
125 { | 119 { |
126 for (size_t i = width; i < m_width; ++i) { | 120 array = (float **)malloc(m_width * sizeof(float *)); |
127 free(array[i]); | 121 if (!array) throw std::bad_alloc(); |
128 } | 122 MUNLOCK(array, m_width * sizeof(float *)); |
129 | 123 |
130 if (width != m_width) { | 124 for (size_t i = 0; i < m_width; ++i) { |
131 array = (float **)realloc(array, width * sizeof(float *)); | 125 array[i] = (float *)malloc(m_height * sizeof(float)); |
132 if (!array) throw std::bad_alloc(); | |
133 MUNLOCK(array, width * sizeof(float *)); | |
134 } | |
135 | |
136 for (size_t i = m_width; i < width; ++i) { | |
137 array[i] = 0; | |
138 } | |
139 | |
140 for (size_t i = 0; i < width; ++i) { | |
141 array[i] = (float *)realloc(array[i], height * sizeof(float)); | |
142 if (!array[i]) throw std::bad_alloc(); | 126 if (!array[i]) throw std::bad_alloc(); |
143 MUNLOCK(array[i], height * sizeof(float)); | 127 MUNLOCK(array[i], m_height * sizeof(float)); |
144 } | 128 } |
145 } | 129 } |
146 | |
147 void | |
148 FFTMemoryCache::reset() | |
149 { | |
150 switch (m_storageType) { | |
151 | |
152 case Compact: | |
153 for (size_t x = 0; x < m_width; ++x) { | |
154 for (size_t y = 0; y < m_height; ++y) { | |
155 m_magnitude[x][y] = 0; | |
156 m_phase[x][y] = 0; | |
157 } | |
158 m_factor[x] = 1.0; | |
159 } | |
160 break; | |
161 | |
162 case Polar: | |
163 for (size_t x = 0; x < m_width; ++x) { | |
164 for (size_t y = 0; y < m_height; ++y) { | |
165 m_fmagnitude[x][y] = 0; | |
166 m_fphase[x][y] = 0; | |
167 } | |
168 m_factor[x] = 1.0; | |
169 } | |
170 break; | |
171 | |
172 case Rectangular: | |
173 for (size_t x = 0; x < m_width; ++x) { | |
174 for (size_t y = 0; y < m_height; ++y) { | |
175 m_freal[x][y] = 0; | |
176 m_fimag[x][y] = 0; | |
177 } | |
178 m_factor[x] = 1.0; | |
179 } | |
180 break; | |
181 } | |
182 } | |
183 | 130 |
184 void | 131 void |
185 FFTMemoryCache::setColumnAt(size_t x, float *mags, float *phases, float factor) | 132 FFTMemoryCache::setColumnAt(size_t x, float *mags, float *phases, float factor) |
186 { | 133 { |
187 Profiler profiler("FFTMemoryCache::setColumnAt: from polar"); | 134 Profiler profiler("FFTMemoryCache::setColumnAt: from polar"); |
188 | 135 |
189 setNormalizationFactor(x, factor); | 136 setNormalizationFactor(x, factor); |
190 | 137 |
191 if (m_storageType == Rectangular) { | 138 if (m_storageType == FFTCache::Rectangular) { |
192 Profiler subprof("FFTMemoryCache::setColumnAt: polar to cart"); | 139 Profiler subprof("FFTMemoryCache::setColumnAt: polar to cart"); |
193 for (size_t y = 0; y < m_height; ++y) { | 140 for (size_t y = 0; y < m_height; ++y) { |
194 m_freal[x][y] = mags[y] * cosf(phases[y]); | 141 m_freal[x][y] = mags[y] * cosf(phases[y]); |
195 m_fimag[x][y] = mags[y] * sinf(phases[y]); | 142 m_fimag[x][y] = mags[y] * sinf(phases[y]); |
196 } | 143 } |
199 setMagnitudeAt(x, y, mags[y]); | 146 setMagnitudeAt(x, y, mags[y]); |
200 setPhaseAt(x, y, phases[y]); | 147 setPhaseAt(x, y, phases[y]); |
201 } | 148 } |
202 } | 149 } |
203 | 150 |
151 m_colsetMutex.lock(); | |
204 m_colset.set(x); | 152 m_colset.set(x); |
153 m_colsetMutex.unlock(); | |
205 } | 154 } |
206 | 155 |
207 void | 156 void |
208 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags) | 157 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags) |
209 { | 158 { |
211 | 160 |
212 float max = 0.0; | 161 float max = 0.0; |
213 | 162 |
214 switch (m_storageType) { | 163 switch (m_storageType) { |
215 | 164 |
216 case Rectangular: | 165 case FFTCache::Rectangular: |
217 for (size_t y = 0; y < m_height; ++y) { | 166 for (size_t y = 0; y < m_height; ++y) { |
218 m_freal[x][y] = reals[y]; | 167 m_freal[x][y] = reals[y]; |
219 m_fimag[x][y] = imags[y]; | 168 m_fimag[x][y] = imags[y]; |
220 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); | 169 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); |
221 if (mag > max) max = mag; | 170 if (mag > max) max = mag; |
222 } | 171 } |
223 break; | 172 break; |
224 | 173 |
225 case Compact: | 174 case FFTCache::Compact: |
226 case Polar: | 175 case FFTCache::Polar: |
227 { | 176 { |
228 Profiler subprof("FFTMemoryCache::setColumnAt: cart to polar"); | 177 Profiler subprof("FFTMemoryCache::setColumnAt: cart to polar"); |
229 for (size_t y = 0; y < m_height; ++y) { | 178 for (size_t y = 0; y < m_height; ++y) { |
230 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); | 179 float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); |
231 float phase = atan2f(imags[y], reals[y]); | 180 float phase = atan2f(imags[y], reals[y]); |
235 } | 184 } |
236 break; | 185 break; |
237 } | 186 } |
238 }; | 187 }; |
239 | 188 |
240 if (m_storageType == Rectangular) { | 189 if (m_storageType == FFTCache::Rectangular) { |
241 m_factor[x] = max; | 190 m_factor[x] = max; |
191 m_colsetMutex.lock(); | |
242 m_colset.set(x); | 192 m_colset.set(x); |
193 m_colsetMutex.unlock(); | |
243 } else { | 194 } else { |
244 setColumnAt(x, reals, imags, max); | 195 setColumnAt(x, reals, imags, max); |
245 } | 196 } |
246 } | 197 } |
247 | 198 |
248 size_t | 199 size_t |
249 FFTMemoryCache::getCacheSize(size_t width, size_t height, StorageType type) | 200 FFTMemoryCache::getCacheSize(size_t width, size_t height, FFTCache::StorageType type) |
250 { | 201 { |
251 size_t sz = 0; | 202 size_t sz = 0; |
252 | 203 |
253 switch (type) { | 204 switch (type) { |
254 | 205 |
255 case Compact: | 206 case FFTCache::Compact: |
256 sz = (height * 2 + 1) * width * sizeof(uint16_t); | 207 sz = (height * 2 + 1) * width * sizeof(uint16_t); |
257 | 208 |
258 case Polar: | 209 case FFTCache::Polar: |
259 case Rectangular: | 210 case FFTCache::Rectangular: |
260 sz = (height * 2 + 1) * width * sizeof(float); | 211 sz = (height * 2 + 1) * width * sizeof(float); |
261 } | 212 } |
262 | 213 |
263 return sz; | 214 return sz; |
264 } | 215 } |