1 /* SSETest.c Testing speed of SSE decode of BWT
3 Copyright 2006, Wong Chi Kwong, all rights reserved.
5 This module tests the speed of SSE decode of BWT.
7 This software may be used freely for any purpose. However, when distributed,
8 the original source must be clearly stated, and, when the source code is
9 distributed, the copyright notice must be retained and any alterations in
10 the code must be clearly marked. No warranty is given regarding the quality
16 #include <emmintrin.h>
18 #include "MiscUtilities.h"
19 #include "MemManager.h"
20 #include "iniparser.h"
25 dictionary
*ParseInput(int argc
, char** argv
);
26 void ValidateParameters();
29 unsigned int MemorySize
;
30 unsigned int NumberOfAccess
;
32 unsigned int NumberOfIteration
;
35 void GenerateDNAOccCountTable1(unsigned int *dnaDecodeTable
) {
37 unsigned int i
, j
, c
, t
;
39 for (i
=0; i
<65536; i
++) {
40 dnaDecodeTable
[i
] = 0;
44 dnaDecodeTable
[i
] += 1 << (t
* 8);
51 int main(int argc
, char** argv
) {
53 #define CHAR_PER_128 64
54 #define CHAR_PER_256 128
55 #define CHAR_PER_WORD 16
58 unsigned int* __restrict address
;
59 unsigned int* __restrict memory
;
60 unsigned int* __restrict dnaDecodeTable
;
61 unsigned int* __restrict index1
;
62 unsigned int* __restrict index2
;
63 unsigned int* __restrict character
;
66 unsigned int t
=0, r
=0, r1
=0;
68 unsigned int t4
[4] = { 0, 0, 0, 0 };
69 unsigned int r4
[4] = { 0, 0, 0, 0 };
70 unsigned int numberOfMemoryLocation
;
72 dictionary
*programInput
;
74 double elapsedTime
= 0, totalElapsedTime
= 0;
75 double initializationTime
, experimentTime
;
77 unsigned int numChar1
, numChar2
, minIndex
, maxIndex
, minIndex128
, maxIndex128
;
79 const static unsigned int ALIGN_16 partitionOne1
[4] = { 47, 31, 15, 0 };
80 const static unsigned int ALIGN_16 partitionOne2
[4] = { 0, 15, 31, 47 };
81 const static unsigned int ALIGN_16 partitionZero1
[4] = { 63, 47, 31, 15 };
82 const static unsigned int ALIGN_16 partitionZero2
[4] = { 15, 31, 47, 63 };
88 // Count one alphabet only
90 __m128i r1a
, r1b
, r1c
;
91 __m128i r2a
, r2b
, r2c
;
93 // Count all alphabets only
100 programInput
= ParseInput(argc
, argv
);
101 ValidateParameters();
103 // Initialize memory manager
104 MMMasterInitialize(0, 0, FALSE
, NULL
);
106 numberOfMemoryLocation
= MemorySize
/ sizeof(int);
109 address
= MMUnitAllocate((NumberOfAccess
+ 8) * sizeof(unsigned int));
110 memory
= MMUnitAllocate((numberOfMemoryLocation
+ 32) * sizeof(unsigned int));
111 index1
= MMUnitAllocate((NumberOfAccess
+ 8) * sizeof(unsigned int));
112 index2
= MMUnitAllocate((NumberOfAccess
+ 8) * sizeof(unsigned int));
113 character
= MMUnitAllocate((NumberOfAccess
+ 8) * sizeof(unsigned int));
115 dnaDecodeTable
= MMUnitAllocate(65536 * sizeof(unsigned int));
118 r250_init(getRandomSeed());
122 startTime
= setStartTime();
124 printf("Initialize memory pointers with random values..");
126 GenerateDNAOccCountTable1(dnaDecodeTable
);
129 for (i
=0; i
<numberOfMemoryLocation
+ 32; i
++) {
132 // Initialize address and memory
133 for (i
=0; i
<NumberOfAccess
+ 8; i
++) {
134 address
[i
] = (r250() % numberOfMemoryLocation
) / 8 * 8; // align to 32 byte
135 index1
[i
] = (r250() % 3) * CHAR_PER_128
;
136 index2
[i
] = r250() % 129;
137 character
[i
] = r250() % 4;
140 printf("finished.\n");
142 elapsedTime
= getElapsedTime(startTime
) - totalElapsedTime
;
143 totalElapsedTime
+= elapsedTime
;
144 initializationTime
= elapsedTime
;
147 if (Mode
[0] == 'S' || Mode
[0] == 's') {
149 for (i
=0; i
<NumberOfIteration
; i
++) {
150 for (j
=0; j
<NumberOfAccess
; j
++) {
152 // Ordering of index1 and index2 is not important; this module will handle the ordering
153 // index1 and index2 can be on the same aligned 128 bit region or can be on adjacant aligned 128 bit region
154 // If index1 and index2 are in the same aligned 128 bit region, one of them must be on the boundary
155 // These requirements are to reduce the no. of branches in the program flow
157 // Pre-fetch next read
158 //_mm_prefetch((char*)(memory + address[j+1]), _MM_HINT_NTA);
159 //_mm_prefetch((char*)(memory + address[j+2]), _MM_HINT_NTA);
160 //_mm_prefetch((char*)(memory + address[j+3]), _MM_HINT_NTA);
161 //_mm_prefetch((char*)(memory + address[j+4]), _MM_HINT_NTA);
163 // Sort index1 and index2
164 temp
= (index1
[j
] - index2
[j
]) & -(index1
[j
] < index2
[j
]);
165 minIndex
= index2
[j
] + temp
;
166 maxIndex
= index1
[j
] - temp
;
168 // Locate 128 bit boundary
169 minIndex128
= lastAlignedBoundary(minIndex
, CHAR_PER_128
);
170 maxIndex128
= lastAlignedBoundary(maxIndex
- (maxIndex
- minIndex
> CHAR_PER_128
), CHAR_PER_128
);
172 // Determine no.of characters to count
173 numChar1
= maxIndex128
- minIndex
;
174 numChar2
= maxIndex
- maxIndex128
;
176 // Set character extraction masks
177 m0
= _mm_set1_epi32(0xFFFFFFFF + (character
[j
] & 1)); // Character selection mask for even bits
178 m1
= _mm_set1_epi32(0xFFFFFFFF + (character
[j
] >> 1)); // Character selection mask for odd bits
179 mcl
= _mm_set1_epi32(0x55555555); // Set bit-clearing mask to 0x55555555....(alternate 1-bit)
181 // Set counting mask for 2 x 128 bits
183 r1a
= _mm_set1_epi32(numChar1
); // Load number of characters into register
184 r2a
= _mm_set1_epi32(numChar2
); // Load number of characters into register
186 r1b
= _mm_load_si128((__m128i
*)partitionOne1
); // Load partition into register
187 r2b
= _mm_load_si128((__m128i
*)partitionOne2
); // Load partition into register
189 r1c
= _mm_load_si128((__m128i
*)partitionZero1
); // Load partition into register
190 r2c
= _mm_load_si128((__m128i
*)partitionZero2
); // Load partition into register
192 r1b
= _mm_cmpgt_epi32(r1a
, r1b
); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
193 r2b
= _mm_cmpgt_epi32(r2a
, r2b
); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
195 r1c
= _mm_cmpgt_epi32(r1a
, r1c
); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
196 r2c
= _mm_cmpgt_epi32(r2a
, r2c
); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
198 r1b
= _mm_srli_epi32(r1b
, (16 - numChar1
% 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
199 r2b
= _mm_slli_epi32(r2b
, (16 - numChar2
% 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
201 r1c
= _mm_or_si128(r1b
, r1c
); // Combine two masks
202 r2c
= _mm_or_si128(r2b
, r2c
); // Combine two masks
204 r1c
= _mm_and_si128(r1c
, mcl
); // Combine with bit-clearing mask (now = 0x55555555....)
205 r2c
= _mm_and_si128(r2c
, mcl
); // Combine with bit-clearing mask (now = 0x55555555....)
207 // Load encoding into register
208 r1e
= _mm_load_si128((__m128i
*)(memory
+ address
[j
] + minIndex128
/ CHAR_PER_WORD
)); // Load encoding into register
209 r2e
= _mm_load_si128((__m128i
*)(memory
+ address
[j
] + maxIndex128
/ CHAR_PER_WORD
)); // Load encoding into register
213 r1b
= _mm_srli_epi32(r1e
, 1); // Shift encoding to right by 1 bit
214 r2b
= _mm_srli_epi32(r2e
, 1); // Shift encoding to right by 1 bit
216 r1a
= _mm_xor_si128(r1e
, m0
); // Check even-bits with mask
217 r2a
= _mm_xor_si128(r2e
, m0
); // Check even-bits with mask
219 r1b
= _mm_xor_si128(r1b
, m1
); // Check odd-bits with mask
220 r2b
= _mm_xor_si128(r2b
, m1
); // Check odd-bits with mask
222 r1a
= _mm_and_si128(r1a
, r1b
); // Combine even and odd bits
223 r2a
= _mm_and_si128(r2a
, r2b
); // Combine even and odd bits
225 r1a
= _mm_and_si128(r1a
, r1c
); // Combine with counting mask, which has been combined with bit-clearing mask of 0x55555555....
226 r2a
= _mm_and_si128(r2a
, r2c
); // Combine with counting mask, which has been combined with bit-clearing mask of 0x55555555....
228 // Combine 2 x 128 bits and continue counting
230 r1a
= _mm_add_epi32(r1a
, r2a
); // Combine 2 x 128 bits by adding them together
232 mcl
= _mm_set1_epi32(0x33333333); // Set bit-clearing mask to 0x33333333....(alternate 2-bits)
234 r1b
= _mm_srli_epi32(r1a
, 2); // Shift intermediate result to right by 2 bit
235 r1a
= _mm_and_si128(r1a
, mcl
); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
236 r1b
= _mm_and_si128(r1b
, mcl
); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
237 r1a
= _mm_add_epi32(r1a
, r1b
); // Combine shifted and non-shifted intermediate results by adding them together
239 mcl
= _mm_set1_epi32(0x0F0F0F0F); // Set bit-clearing mask to 0x0F0F0F0F....(alternate 4-bits)
240 m0
= _mm_setzero_si128(); // Set an all-zero mask
242 r1b
= _mm_srli_epi32(r1a
, 4); // Shift intermediate result to right by 2 bit
243 r1a
= _mm_add_epi32(r1a
, r1b
); // Combine shifted and non-shifted intermediate results by adding them together
244 r1a
= _mm_and_si128(r1a
, mcl
); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
246 r1a
= _mm_sad_epu8(r1a
, m0
); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
248 r
= _mm_extract_epi16(r1a
, 0) + _mm_extract_epi16(r1a
, 4); // Extract result from register and store into variable
251 if (index1[j] < index2[j]) {
252 r1 = ForwardDNAOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index2[j] - index1[j], character[j], dnaDecodeTable);
254 r1 = BackwardDNAOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index1[j] - index2[j], character[j], dnaDecodeTable);
267 // Test SSE Decode all alphabets
268 if (Mode
[0] == 'A' || Mode
[0] == 'a') {
270 for (i
=0; i
<NumberOfIteration
; i
++) {
271 for (j
=0; j
<NumberOfAccess
; j
++) {
273 // Ordering of index1 and index2 is not important; this module will handle the ordering
274 // index1 and index2 can be on the same aligned 128 bit region or can be on adjacant aligned 128 bit region
275 // If index1 and index2 are in the same aligned 128 bit region, one of them must be on the boundary
276 // These requirements are to reduce the no. of branches in the program flow
278 // Pre-fetch next read
279 //_mm_prefetch((char*)(memory + address[j+1]), _MM_HINT_NTA);
280 //_mm_prefetch((char*)(memory + address[j+2]), _MM_HINT_NTA);
281 //_mm_prefetch((char*)(memory + address[j+3]), _MM_HINT_NTA);
282 //_mm_prefetch((char*)(memory + address[j+4]), _MM_HINT_NTA);
284 // Sort index1 and index2
285 r
= (index1
[j
] - index2
[j
]) & -(index1
[j
] < index2
[j
]);
286 minIndex
= index2
[j
] + r
;
287 maxIndex
= index1
[j
] - r
;
289 // Locate 128 bit boundary
290 minIndex128
= lastAlignedBoundary(minIndex
, CHAR_PER_128
);
291 maxIndex128
= lastAlignedBoundary(maxIndex
- (maxIndex
- minIndex
> CHAR_PER_128
), CHAR_PER_128
);
293 // Determine no.of characters to count
294 numChar1
= maxIndex128
- minIndex
;
295 numChar2
= maxIndex
- maxIndex128
;
297 // Set character extraction masks
298 mcl
= _mm_set1_epi32(0x55555555); // Set bit-clearing mask to 0x55555555....(alternate 1-bit)
300 // Set counting mask for 2 x 128 bits
301 ra1
= _mm_set1_epi32(numChar1
); // Load number of characters into register
302 ra2
= _mm_set1_epi32(numChar2
); // Load number of characters into register
304 rc1
= _mm_load_si128((__m128i
*)partitionOne1
); // Load partition into register
305 rc2
= _mm_load_si128((__m128i
*)partitionOne2
); // Load partition into register
307 rg1
= _mm_load_si128((__m128i
*)partitionZero1
); // Load partition into register
308 rg2
= _mm_load_si128((__m128i
*)partitionZero2
); // Load partition into register
310 rc1
= _mm_cmpgt_epi32(ra1
, rc1
); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
311 rc2
= _mm_cmpgt_epi32(ra2
, rc2
); // Compare to generate 4x32 bit mask; the word with counting boundary is all ones
313 rg1
= _mm_cmpgt_epi32(ra1
, rg1
); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
314 rg2
= _mm_cmpgt_epi32(ra2
, rg2
); // Compare to generate 4x32 bit mask; the word with counting boundary is all zeros
316 rc1
= _mm_srli_epi32(rc1
, (16 - numChar1
% 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
317 rc2
= _mm_slli_epi32(rc2
, (16 - numChar2
% 16) * 2); // Shift bits so that all word comform to the requirement of counting the word with counting boundary
319 ra1
= _mm_or_si128(rc1
, rg1
); // Combine two masks
320 ra2
= _mm_or_si128(rc2
, rg2
); // Combine two masks
322 // Load encoding into register
323 r1e
= _mm_load_si128((__m128i
*)(memory
+ address
[j
] + minIndex128
/ CHAR_PER_WORD
)); // Load encoding into register
324 r2e
= _mm_load_si128((__m128i
*)(memory
+ address
[j
] + maxIndex128
/ CHAR_PER_WORD
)); // Load encoding into register
327 r1e
= _mm_and_si128(r1e
, ra1
); // Combine encoding with counting mask
328 r2e
= _mm_and_si128(r2e
, ra2
); // Combine encoding with counting mask
330 // ra1, ra2, rc1, rc2, rg1, rg2, rt1, rt2 all retired
332 // Shift and combine with character selection mask
334 ra1
= _mm_srli_epi32(r1e
, 1); // Shift encoding to right by 1 bit
335 ra2
= _mm_srli_epi32(r2e
, 1); // Shift encoding to right by 1 bit
337 rt1
= _mm_and_si128(r1e
, mcl
); // Check even-bits = '1'
338 rt2
= _mm_and_si128(r2e
, mcl
); // Check even-bits = '1'
340 rg1
= _mm_and_si128(ra1
, mcl
); // Check odd-bits = '1'
341 rg2
= _mm_and_si128(ra2
, mcl
); // Check odd-bits = '1'
343 rc1
= _mm_andnot_si128(r1e
, mcl
); // Check even-bits = '0'
344 rc2
= _mm_andnot_si128(r2e
, mcl
); // Check even-bits = '0'
346 ra1
= _mm_andnot_si128(ra1
, mcl
); // Check odd-bits = '0'
347 ra2
= _mm_andnot_si128(ra2
, mcl
); // Check odd-bits = '0'
351 // Count for 'c' 'g' 't'
353 r1e
= _mm_and_si128(ra1
, rt1
); // Combine even and odd bits
354 r2e
= _mm_and_si128(ra2
, rt2
); // Combine even and odd bits
355 ra1
= _mm_and_si128(rg1
, rc1
); // Combine even and odd bits
356 ra2
= _mm_and_si128(rg2
, rc2
); // Combine even and odd bits
357 rc1
= _mm_and_si128(rg1
, rt1
); // Combine even and odd bits
358 rc2
= _mm_and_si128(rg2
, rt2
); // Combine even and odd bits
360 rc
= _mm_add_epi32(r1e
, r2e
); // Combine 2 x 128 bits by adding them together
361 rg
= _mm_add_epi32(ra1
, ra2
); // Combine 2 x 128 bits by adding them together
362 rt
= _mm_add_epi32(rc1
, rc2
); // Combine 2 x 128 bits by adding them together
364 // All except rc, rg, rt retired
366 // Continue counting rc, rg, rt
368 mcl
= _mm_set1_epi32(0x33333333); // Set bit-clearing mask to 0x33333333....(alternate 2-bits)
370 rc1
= _mm_srli_epi32(rc
, 2); // Shift intermediate result to right by 2 bit
371 rg1
= _mm_srli_epi32(rg
, 2); // Shift intermediate result to right by 2 bit
372 rt1
= _mm_srli_epi32(rt
, 2); // Shift intermediate result to right by 2 bit
374 rc2
= _mm_and_si128(rc
, mcl
); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
375 rg2
= _mm_and_si128(rg
, mcl
); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
376 rt2
= _mm_and_si128(rt
, mcl
); // Clear alternate 2-bits of intermediate result by combining with bit-clearing mask (now = 0x33333333....)
378 rc1
= _mm_and_si128(rc1
, mcl
); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
379 rg1
= _mm_and_si128(rg1
, mcl
); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
380 rt1
= _mm_and_si128(rt1
, mcl
); // Clear alternate 2-bits of shifted intermediate result by combining with bit-clearing mask (now = 0x33333333....)
382 rc
= _mm_add_epi32(rc1
, rc2
); // Combine shifted and non-shifted intermediate results by adding them together
383 rg
= _mm_add_epi32(rg1
, rg2
); // Combine shifted and non-shifted intermediate results by adding them together
384 rt
= _mm_add_epi32(rt1
, rt2
); // Combine shifted and non-shifted intermediate results by adding them together
386 mcl
= _mm_set1_epi32(0x0F0F0F0F); // Set bit-clearing mask to 0x0F0F0F0F....(alternate 4-bits)
387 r1e
= _mm_setzero_si128(); // Set an all-zero mask
389 rc1
= _mm_srli_epi32(rc
, 4); // Shift intermediate result to right by 2 bit
390 rg1
= _mm_srli_epi32(rg
, 4); // Shift intermediate result to right by 2 bit
391 rt1
= _mm_srli_epi32(rt
, 4); // Shift intermediate result to right by 2 bit
393 rc2
= _mm_add_epi32(rc
, rc1
); // Combine shifted and non-shifted intermediate results by adding them together
394 rg2
= _mm_add_epi32(rg
, rg1
); // Combine shifted and non-shifted intermediate results by adding them together
395 rt2
= _mm_add_epi32(rt
, rt1
); // Combine shifted and non-shifted intermediate results by adding them together
397 rc
= _mm_and_si128(rc2
, mcl
); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
398 rg
= _mm_and_si128(rg2
, mcl
); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
399 rt
= _mm_and_si128(rt2
, mcl
); // Clear alternate 4-bits of intermediate result by combining with bit-clearing mask (now = 0xOFOFOFOF....)
401 rc
= _mm_sad_epu8(rc
, r1e
); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
402 rg
= _mm_sad_epu8(rg
, r1e
); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
403 rt
= _mm_sad_epu8(rt
, r1e
); // Treating the 128 bit as 16 x 8 bit; summing up the 1st 8 x 8 bit into 1st 64-bit and 2nd 8 x 8 bit into 2nd 64-bit
405 r4
[1] = _mm_extract_epi16(rc
, 0) + _mm_extract_epi16(rc
, 4); // Extract result from register and store into variable
406 r4
[2] = _mm_extract_epi16(rg
, 0) + _mm_extract_epi16(rg
, 4); // Extract result from register and store into variable
407 r4
[3] = _mm_extract_epi16(rt
, 0) + _mm_extract_epi16(rt
, 4); // Extract result from register and store into variable
409 r4
[0] = maxIndex
- minIndex
- r4
[1] - r4
[2] - r4
[3];
412 if (index1[j] < index2[j]) {
413 ForwardDNAAllOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index2[j] - index1[j], t4, dnaDecodeTable);
415 BackwardDNAAllOccCount(memory + address[j] + index1[j] / CHAR_PER_WORD, index1[j] - index2[j], t4, dnaDecodeTable);
417 if (r4[0] != t4[0] || r4[1] != t4[1] || r4[2] != t4[2] || r4[3] != t4[3]) {
432 // Test decode by lookup
433 if (Mode
[0] == 'L' || Mode
[0] == 'l') {
434 for (i
=0; i
<NumberOfIteration
; i
++) {
435 for (j
=0; j
<NumberOfAccess
; j
++) {
437 // Pre-fetch next read
438 //_mm_prefetch((char*)(memory + address[j+1]), _MM_HINT_T0);
439 //_mm_prefetch((char*)(memory + address[j+2]), _MM_HINT_NTA);
440 //_mm_prefetch((char*)(memory + address[j+3]), _MM_HINT_NTA);
441 //_mm_prefetch((char*)(memory + address[j+4]), _MM_HINT_NTA);
443 if (index1
[j
] < index2
[j
]) {
444 r
= ForwardDNAOccCount(memory
+ address
[j
] + index1
[j
] / CHAR_PER_WORD
, index2
[j
] - index1
[j
], character
[j
], dnaDecodeTable
);
446 r
= BackwardDNAOccCount(memory
+ address
[j
] + index1
[j
] / CHAR_PER_WORD
, index1
[j
] - index2
[j
], character
[j
], dnaDecodeTable
);
455 elapsedTime
= getElapsedTime(startTime
) - totalElapsedTime
;
456 totalElapsedTime
+= elapsedTime
;
457 experimentTime
= elapsedTime
;
459 // So that compiler does not remove code for variables t and r
460 if ((Mode
[0] == 'S' || Mode
[0] == 's' || Mode
[0] == 'L' || Mode
[0] == 'l') && t
== 0) {
463 if ((Mode
[0] == 'A' || Mode
[0] == 'a') && t4
[0] == 0 && t4
[1] == 0 && t4
[2] == 0 && t4
[3] == 0) {
467 printf("Experiment completed.\n");
469 printf("Initialization time = ");
470 printElapsedTime(stdout
, FALSE
, FALSE
, TRUE
, 2, initializationTime
);
471 printf("Experiment time = ");
472 printElapsedTime(stdout
, FALSE
, FALSE
, TRUE
, 2, experimentTime
);
474 MMUnitFree(address
, (NumberOfAccess
+ 8) * sizeof(unsigned int));
475 MMUnitFree(memory
, (numberOfMemoryLocation
+ 32) * sizeof(unsigned int));
476 MMUnitFree(index1
, (NumberOfAccess
+ 8) * sizeof(unsigned int));
477 MMUnitFree(index2
, (NumberOfAccess
+ 8) * sizeof(unsigned int));
478 MMUnitFree(character
, (NumberOfAccess
+ 8) * sizeof(unsigned int));
479 MMUnitFree(dnaDecodeTable
, 65536 * sizeof(unsigned int));
481 iniparser_freedict(programInput
);
487 dictionary
*ParseInput(int argc
, char** argv
) {
489 dictionary
*programInput
;
491 programInput
= paraparser_load(argc
, argv
, 0, NULL
);
493 MemorySize
= iniparser_getint(programInput
, "argument:1", 0);
495 fprintf(stderr
, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv
[0]);
498 NumberOfAccess
= iniparser_getint(programInput
, "argument:2", 0);
499 if (!NumberOfAccess
) {
500 fprintf(stderr
, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv
[0]);
503 Mode
= iniparser_getstring(programInput
, "argument:3", 0);
504 if (!NumberOfAccess
) {
505 fprintf(stderr
, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv
[0]);
508 NumberOfIteration
= iniparser_getint(programInput
, "argument:4", 0);
509 if (!NumberOfIteration
) {
510 fprintf(stderr
, "Syntax: %s <Memory size> <Number of Access> <SSE/Lookup> <No. of iteration>\n", argv
[0]);
518 void ValidateParameters() {
520 if (MemorySize
== 0) {
521 fprintf(stderr
, "Memory Size = 0!\n");
524 if (MemorySize
% 4 != 0) {
525 fprintf(stderr
, "Memory Size must be multiple of 4!\n");
528 if (NumberOfAccess
== 0) {
529 fprintf(stderr
, "Number of Access = 0!\n");
532 if (Mode
[0] != 'S' && Mode
[0] != 's' && Mode
[0] != 'L' && Mode
[0] != 'l' && Mode
[0] != 'A' && Mode
[0] != 'a') {
533 fprintf(stderr
, "Testing must be SSE, All alphabet SSE or Lookup!\n");
536 if (NumberOfIteration
== 0) {
537 fprintf(stderr
, "Number of Iteration = 0!\n");