]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/MUONTimeRawStreamTracker.C
Add a protection against division by 0 (which may occur when a track exit from the...
[u/mrichter/AliRoot.git] / MUON / MUONTimeRawStreamTracker.C
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * All rights reserved.                                                   *
4  *                                                                        *
5  * Primary Authors:                                                       *
6  *   Artur Szostak <artursz@iafrica.com>                                  *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /// \ingroup macros
18 /// \file MUONTimeRawStreamTracker.C
19 /// \brief Macro for checking the timing (speed) performance of the tracker decoder.
20 ///
21 /// \author Artur Szostak <artursz@iafrica.com>
22 ///
23 /// This macro is used to check the timing (speed) performance of the 
24 /// decoder for the tracker DDLs. It can be invoked as follows:
25 /// 
26 ///  $ aliroot
27 /// .L $ALICE_ROOT/MUON/MUONTimeRawStreamTracker.C+
28 ///  MUONTimeRawStreamTracker(filename, maxEvent);
29 ///
30 /// where \em filename is the name of a file containing the raw data, or alternatively
31 /// the directory containing rawX (X being an integer) paths with the raw DDL
32 /// data. The \em maxEvent value is the maximum event to process (default set to
33 /// 1000). Thus the macro will time the algorithm for all events in the range
34 /// [0 .. maxEvent-1].
35 ///
36
37 #if !defined(__CINT__) || defined(__MAKECINT__)
38
39 #include "AliCodeTimer.h"
40
41 // MUON includes
42 #include "AliMUONRawStreamTrackerHP.h"
43 #include "AliMUONDspHeader.h"
44 #include "AliMUONBlockHeader.h"
45 #include "AliMUONBusStruct.h"
46 #include "AliMUONDDLTracker.h"
47
48 // RAW includes
49 #include "AliRawReader.h"
50 #include "AliRawReaderMemory.h"
51 #include "AliRawDataHeader.h"
52
53 #include "TStopwatch.h"
54 #include "TMath.h"
55 #include "Riostream.h"
56
57 #endif
58
59
60 // Linked list node for buffer structures.
61 struct AliBufferInfo
62 {
63         AliBufferInfo* fNext;
64         Int_t fEquipId;
65         UInt_t fBufferSize;
66         UChar_t* fBuffer;
67 };
68
69
70 // Digit information to store
71 struct AliDigitInfo
72 {
73         UShort_t fManuId;
74         UShort_t fAdc;
75         UChar_t fChannelId;
76 };
77
78
79 UInt_t LoadFiles(AliBufferInfo*& list, TString fileName = "./", Int_t maxEvent = 1000)
80 {
81         /// Reads in the DDL files into memory buffers as a linked list.
82
83         AliRawReader* rawReader = AliRawReader::Create(fileName.Data()); 
84
85         if (rawReader == NULL)
86         {
87                 cerr << "ERROR: Could not create AliRawReader." << endl;
88                 delete rawReader;
89                 return 0;
90         }
91
92         UInt_t count = 0;
93         Int_t iEvent = 0;
94         list = NULL;
95         while (rawReader->NextEvent())
96         {
97                 if (iEvent++ >= maxEvent) break;
98
99                 rawReader->Select("MUONTRK", 0, 19);
100                 while (rawReader->ReadHeader())
101                 {
102                         AliBufferInfo* info = new AliBufferInfo;
103                         if (info == NULL)
104                         {
105                                 cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
106                                 delete rawReader;
107                                 return count;
108                         }
109                         info->fNext = list;
110                         info->fEquipId = rawReader->GetEquipmentId();
111                         info->fBufferSize = rawReader->GetDataSize() + sizeof(AliRawDataHeader);
112                         info->fBuffer = new UChar_t[info->fBufferSize];
113                         if (info->fBuffer == NULL)
114                         {
115                                 cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
116                                 delete rawReader;
117                                 return count;
118                         }
119                         list = info;
120                         
121                         // Copy the header.
122                         memcpy(info->fBuffer, rawReader->GetDataHeader(), sizeof(AliRawDataHeader));
123
124                         // Now copy the payload.
125                         if (! rawReader->ReadNext(
126                                                 info->fBuffer + sizeof(AliRawDataHeader),
127                                                 info->fBufferSize - sizeof(AliRawDataHeader)
128                                         )
129                            )
130                         {
131                                 cerr << "ERROR: Failed to read from AliRawReader." << endl;
132                         }
133                         count++;
134                 }
135         }
136
137         delete rawReader;
138         return count;
139 }
140
141
142 UInt_t CountMaxDigits(AliBufferInfo* list)
143 {
144         /// Counts the maximum number of digits possible in all the buffers.
145
146         UInt_t total = 0;
147         AliBufferInfo* current = list;
148         while (current != NULL)
149         {
150                 total += current->fBufferSize;
151                 current = current->fNext;
152         }
153         return total;
154 }
155
156
157 void ReleaseBuffers(AliBufferInfo* list)
158 {
159         /// Deletes the memory allocated for the linked list of buffers.
160
161         AliBufferInfo* current = list;
162         while (current != NULL)
163         {
164                 AliBufferInfo* tmp = current;
165                 current = current->fNext;
166                 delete [] tmp->fBuffer;
167                 delete tmp;
168         }
169 }
170
171
172 Double_t TimeDecoderBusPatchIteration(AliBufferInfo* list, AliDigitInfo* buffer, UInt_t maxBufferSize)
173 {
174         /// Perform a timing using the new decoder using the "next bus patch" iteration
175
176         AliRawReaderMemory rawReader;
177         AliMUONRawStreamTrackerHP rawStream(&rawReader);
178         rawReader.NextEvent();
179
180         TStopwatch timer;
181         timer.Start(kTRUE);
182
183         UInt_t i = 0;
184         AliBufferInfo* current = list;
185         while (current != NULL)
186         {
187                 rawReader.SetMemory(current->fBuffer, current->fBufferSize);
188                 rawReader.SetEquipmentID(current->fEquipId);
189                 rawReader.Reset();
190
191                 UShort_t manuId, adc;
192                 UChar_t manuChannel;
193
194                 rawStream.First();
195
196                 const AliMUONRawStreamTrackerHP::AliBusPatch* buspatch = NULL;
197                 while ((buspatch = rawStream.Next()) != NULL)
198                 {
199                         for (UInt_t j = 0; j < buspatch->GetDataCount(); j++)
200                         {
201                                 buspatch->GetData(j, manuId, manuChannel, adc);
202                                 if (i < maxBufferSize)
203                                 {
204                                         buffer[i].fManuId = manuId;
205                                         buffer[i].fAdc = adc;
206                                         buffer[i].fChannelId = manuChannel;
207                                         i++;
208                                 }
209                         }
210                 }
211
212                 current = current->fNext;
213         }
214
215         return timer.RealTime();
216 }
217
218
219 Double_t TimeDecoderChannelIteration(AliBufferInfo* list, AliDigitInfo* buffer, UInt_t maxBufferSize, Bool_t skipParityErrors)
220 {
221         /// Perform a timing using the "next channel" iteration
222   
223         AliRawReaderMemory rawReader;
224         AliMUONRawStreamTrackerHP rawStream(&rawReader);
225         rawReader.NextEvent();
226
227         TStopwatch timer;
228         timer.Start(kTRUE);
229
230         UInt_t i = 0;
231         AliBufferInfo* current = list;
232         while (current != NULL)
233         {
234                 rawReader.SetMemory(current->fBuffer, current->fBufferSize);
235                 rawReader.SetEquipmentID(current->fEquipId);
236                 rawReader.Reset();
237
238                 Int_t busPatch;
239                 UShort_t manuId, adc;
240                 UChar_t manuChannel;
241
242                 rawStream.First();
243
244                 while ( rawStream.Next(busPatch,manuId,manuChannel,adc,skipParityErrors) )
245                 {
246                         if (i < maxBufferSize)
247                         {
248                                 buffer[i].fManuId = manuId;
249                                 buffer[i].fAdc = adc;
250                                 buffer[i].fChannelId = manuChannel;
251                                 i++;
252                         }
253                 }
254
255                 current = current->fNext;
256         }
257
258         return timer.RealTime();
259 }
260
261 void MUONTimeRawStreamTrackerDumb(TString fileName)
262 {
263   AliCodeTimer::Instance()->Reset();
264   
265   // first check we can open the stream
266   AliRawReader* reader = AliRawReader::Create(fileName.Data());
267   if (!reader)
268   {
269     cerr << "Cannot create reader from " << fileName.Data() << endl;
270     return;
271   }
272   
273   AliMUONRawStreamTrackerHP stream(reader);
274   
275   Int_t busPatch;
276   UShort_t manuId, adc;
277   UChar_t manuChannel;
278   
279   while ( reader->NextEvent() ) 
280   {
281     stream.First();
282     
283     while ( stream.Next(busPatch,manuId,manuChannel,adc) ) 
284     {
285       adc *= 2;
286     }
287   }
288   
289   AliCodeTimer::Instance()->Print();
290 }
291
292
293 void MUONTimeRawStreamTracker(TString fileName = "./", Int_t maxEvent = 1000)
294 {
295         /// Performs a timing of decoder
296
297         AliBufferInfo* list = NULL;
298         UInt_t bufferCount = LoadFiles(list, fileName, maxEvent);
299         if (bufferCount == 0)
300         {
301                 cerr << "ERROR: No DDL files found or read in." << endl;
302                 return;
303         }
304
305         UInt_t maxBufferSize = CountMaxDigits(list);
306         AliDigitInfo* buffer = new AliDigitInfo[maxBufferSize];
307         if (buffer == NULL)
308         {
309                 ReleaseBuffers(list);
310                 cerr << "ERROR: Out of memory, sorry. You should limit the number of events read in." << endl;
311                 return;
312         }
313         Double_t bpTimes[100];
314         for (Int_t i = 0; i < 100; i++)
315         {
316                 cout << "Timing decoder: bus patch iteration " << i+1 << " of 100" << endl;
317                 bpTimes[i] = TimeDecoderBusPatchIteration(list, buffer, maxBufferSize);
318         }
319         Double_t channelTimes[100];
320         for (Int_t i = 0; i < 100; i++)
321         {
322                 cout << "Timing decoder: channel iteration w/ parity check" << i+1 << " of 100" << endl;
323                 channelTimes[i] = TimeDecoderChannelIteration(list, buffer, maxBufferSize,kTRUE);
324         }
325         Double_t channelTimes2[100];
326         for (Int_t i = 0; i < 100; i++)
327         {
328                 cout << "Timing decoder: channel iteration w/o parity check" << i+1 << " of 100" << endl;
329                 channelTimes2[i] = TimeDecoderChannelIteration(list, buffer, maxBufferSize,kFALSE);
330         }
331   
332         ReleaseBuffers(list);
333         delete buffer;
334
335         Double_t bpTime = TMath::Mean(100, bpTimes) / Double_t(bufferCount);
336         Double_t bpTimeErr = TMath::RMS(100, bpTimes) / Double_t(bufferCount);
337         Double_t channelTime = TMath::Mean(100, channelTimes) / Double_t(bufferCount);
338         Double_t channelTimeErr = TMath::RMS(100, channelTimes) / Double_t(bufferCount);
339         Double_t channelTime2 = TMath::Mean(100, channelTimes2) / Double_t(bufferCount);
340         Double_t channelTime2Err = TMath::RMS(100, channelTimes2) / Double_t(bufferCount);
341
342         cout << "Average processing time per DDL for:" << endl;
343         cout << "   bus patch iteration                    = " << bpTime*1e6 << " +/- " << bpTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
344         cout << "   channel iteration with parity check    = " << channelTime*1e6 << " +/- " << channelTimeErr*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
345         cout << "   channel iteration without parity check = " << channelTime2*1e6 << " +/- " << channelTime2Err*1e6/TMath::Sqrt(100) << " micro seconds" << endl;
346 }
347