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 }