C代码-内存访问/抢占

C代码-内存访问/抢占,c,memory-management,preemption,C,Memory Management,Preemption,我编写了一段代码,其中一个数据: unsigned char buf[4096]; // data in chunks of size 4k unsigned counter[256]; 我将每3个连续字节的I/p数据相加,并存储ans。 例如:温度[4096];温度[0]=buf[0]+buf[1]+buf[2]。。。到4096年 然后使用以下代码从temp结果生成直方图: for(i = 0; i < 4096; i++) counter[temp[i]]++; (i=0;ibes

我编写了一段代码,其中一个数据:

unsigned char buf[4096]; // data in chunks of size 4k
unsigned counter[256];
我将每3个连续字节的I/p数据相加,并存储ans。 例如:温度[4096];温度[0]=buf[0]+buf[1]+buf[2]。。。到4096年

然后使用以下代码从temp结果生成直方图:

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

计数器[温度[i]]++;
对直方图进行排序(气泡排序),然后取前8个最经常出现的值。代码在linux内核(2.6.35)中运行


我面临的问题是,如果删除排序部分,执行代码所需的时间非常快(在我的笔记本电脑上为6微秒,使用gettimeofday func测量)。但在引入排序后,过程在很大程度上减慢了(44微秒)。排序功能本身需要20微秒,我不明白为什么时间会增加这么多。我用cachegrind做了一个内存分析,结果是正常的,我甚至试过禁用抢占UB,但仍然没有显示任何差异。如果有人能帮我的话。谢谢

气泡排序很慢。。。O(N^2)复杂性。。。如果您想要更快的性能,可以使用堆之类的数据结构,或者在阵列上运行快速排序算法,这两种算法都会给排序过程带来O(N log N)复杂度。此外,这两种方法在固定长度数组上也能很好地工作。

气泡排序速度很慢,它会比较和交换您的值,最多4096*4096=16777216次。如果只需要8个最佳值,则1扫描选择肯定会更快。差不多吧

 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. */
   }
 }
常数n=8;
uint_t best[n]={0};
单位索引[n]={0};
uint_t j;
对于(uint_t i=0;i最佳[n-1]){
对于(j=n-2;j&&counter[i]>best[j];j--);/*查找插入位置,因为我们的值可能大于位置n-1处的值*/
memmove(&best[j+1],&best[j],(n-1-j)*最佳值的大小[0]);/*将j以外的值向上移动1*/
memmove(&index[j+1],&index[j],(n-1-j)*索引[0]的大小);
最佳[j]=计数器[i];/*将当前最佳值置于顶部*/
index[j]=i;/*将索引存储在第二个数组中,以了解最佳值的位置*/
}
}
这样,您只需比较一次值,
memmove
的成本可以忽略不计,因为您的选择数组很小。 无需对数组进行排序,此算法为O(nm),n为数组大小,m为选择的大小。最好的排序是O((n.log2n).m)。所以,如果m很小,n很大,它是任何通用排序算法都无法比拟的

编辑:我为索引添加了数组

EDIT2:引入第二个来纠正我在第一个实例中遇到的基本错误


EDIT3:注释:
memmove
大小为0是允许的,基本上是nop

为什么是气泡排序?为什么不
qsort()
?要获得8个最大值,无需进行完全排序。例如,Heapsort可用于获取N个顶级值(如果实现的话),它将比完全排序更快。甚至比选择排序更快-在获取前8个值后可以停止选择排序。在引入排序时,您的代码的哪一部分占用了其他18微秒?您是否以某种方式使用动态内存(
malloc
和朋友)???我已经为sort创建了一个结构,其中包含值及其计数器,即它出现的次数。排序循环正在运行8 x 256次。您的代码似乎有点错误。您实现了什么排序方法?没有排序方法,我从计数器数组中选择最高值。当然,如果您想知道
计数器
的哪个索引最高,您还必须将其存储在一个数组中,该数组与
memmove
同步。如果您将
n
设为4096,这将是一种选择排序。正常选择排序的复杂度是O(n^2),但当我们将
memmove
限制为一个小的常量值时,我们得到了O(8n)=O(n)。我在这里看到的唯一问题是,如果您在早期遇到一个非常大的值。。。假设您首先遇到的直方图值是最大的直方图值。现在,您将永远不会看到其他七个值小于初始(最大)直方图值,因为
if(counter[i]>best[0])
将始终为false。所以在这种情况下,你只会得到最大的直方图值,而不是最大的八个直方图值。。。最佳数组的其余部分将是零。是的,你说得对,我从我的应用程序中复制了它,但忘记了关键部分。对不起,我马上更正。