Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C code - memory access / preemption

I have written a piece of code wherein a data:

unsigned char buf[4096]; // data in chunks of size 4k
unsigned counter[256];

I am adding up the i/p data for every 3 contiguous bytes and storing the ans. ex: temp[4096]; temp[0] = buf[0] + buf[1] + buf[2]; ... till 4096

Then a histogram is generated from the results of temp using the code:

for(i = 0; i < 4096; i++)
counter[temp[i]]++;

The histogram is sorted (bubble sort) and then top 8 most recurring values are taken. The code is run in the linux kernel (2.6.35)

The problem I am facing is that if I remove the sorting part, the time taken to execute the code is very fast (6 microsec on my laptop, measured using gettimeofday func). But after introducing the sorting, the process slows down to a great extent (44 microsec). The sorting function itself takes 20 microsecs, I cant understand why is the time then increasing so much. I did a memory analysis using cachegrind, the results are normal and I even tried disabling preemption ubut still it doesnt show any difference. If anybody can help me out over here. Thanks!

like image 593
randy7 Avatar asked Jul 05 '11 13:07

randy7


2 Answers

Bubble sort is slow, it compares and swaps your values up to 4096*4096 = 16,777,216 times. If you need only the 8 best values, a 1 sweep selection is certainly faster. Something like that.

 const uint_t n = 8;
 uint_t best[n] = {0};
 uint_t index[n] = {0};
 uint_t j;

 for(uint_t i=0; i<4096; i++) {

   if(counter[i] > best[n-1]) {
     for(j=n-2; j && counter[i] > best[j]; j--);           /* Find the insertion position, as our value might be bigger than the value at position n-1. */
     memmove(&best [j+1], &best[j] , (n-1 -j) * sizeof best[0]);      /* Shift the values beyond j up 1  */
     memmove(&index[j+1], &index[j], (n-1 -j) * sizeof index[0]);
     best[j] = counter[i];                                 /* Put the current best value at the top */
     index[j] = i;                                         /* Store the index in the second array to know where the best value was. */
   }
 }

With that, you compare your values only once and the cost of the memmove is negligible because your selection array is small. No need to sort the array, this algo is O(nm) with n the size of your array and m the size of your selection. The best sort would be O((n.log2 n).m). So if m is small and n is big, it is unbeatable by any generic sort algorithm.

EDIT: I added the array for the index.

EDIT2: Introduced second to correct the fundamental bug I had in first instance.

EDIT3: Comment: memmove with size 0 is allowed and is basically a nop.

like image 154
Patrick Schlüter Avatar answered Nov 06 '22 07:11

Patrick Schlüter


Bubble sort is slow ... O(N^2) complexity ... if you want faster performance, use a data-structure like a heap, or run the quick-sort algorithm on your array, both of which will give you O(N log N) complexity for the sorting process. In addition, both methods will also work nicely on fixed-length arrays.

like image 32
Jason Avatar answered Nov 06 '22 07:11

Jason