NandFlash驱动中遇到的算法问题,请各位高手给点提示。

gsymichael 2009-02-25 10:40:48
本人是做WinCE下的驱动的,在驱动中碰到一个问题,目前没有很好的方法解决,请各位高手给点提示。

问题是这样的:由于NandFlash的特性,在某个特定的物理页在被多次读取后,和它对应的一个页上有可能会出现不可校正的ECC错误,为了减少这种问题发生的几率,考虑在驱动中加入Cache的功能,将一段时间内读次数最多的若干个页Cache起来。在Cache起来之后,以后对于这些页的读取就只是从Cache中读取,而不需要从Flash上读取数据。

在驱动中在读取页的函数中加入了计数,目前使用一个数组,数组下标代表页号,数组内容记录被读取的次数。
最开始的做法是在每隔3分钟时,循环查询这个数组,第一次将读次数最多的记录下来,第二次记录读次数第二多的,依次记录100个页。发现以目前的Flash大小(256MB,一共65535个页)需要9秒多,这个时间没法满足要求。

后来有人提示说可以用快速排序的方法来做,我就又采用快速排序的方法来做,考虑到我实际上并不关心得到的100个页必须按由高到低的次序排列,我只需要这100个页的读次数是最多即可。我又修改了一下快速排序的方法,好比按由高到低来排序,如果第一次排序之后发现左边的项已经大于10,那么就只需要在左边做递归;如果小于100,那么只需要在右边做递归,同时将这个需求值减掉左边的项的数目。这样的话应该能减少很多的计算。但是通过这个方法发现还是需要9秒多的时间。

问题就是这样,有没有什么好方法可以很快的找到100个被读取次数最多的页,而对这100个页其实并不关心是否按序排列。
...全文
101 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
绿色夹克衫 2009-02-25
  • 打赏
  • 举报
回复
好像有个nth_element,可以用线性时间找到第100项,转贴一段代码

然后再遍历一下65535个,就能找出前100项了.

不过感觉LZ的问题有可能不在排序算法上,按理说使用快速排序后,效率应该已经能够提高很多,不应该还是9秒


void swap( int& a, int& b )
{
if ( a == b ) return;
a ^= b;
b ^= a;
a ^= b;
}

int partation( int* arr, int low, int high )
{
int ans = low - 1;
for ( int i = low; i < high; ++i )
{
if ( arr[i] < arr[high] )
{
swap( arr[i], arr[++ans] );
}
}
swap( arr[++ans], arr[high] );
return ans;
}

int nth( int* arr, int low, int high, int index )
{
int mid = partation(arr, low, high);
if ( mid == index ) return arr[mid];
return
( mid < index ) ?
nth(arr, mid+1, high, index) :
nth(arr, low, mid-1, index);
}
medie2005 2009-02-25
  • 打赏
  • 举报
回复
你的快速排序是怎么实现的?按理不会那么慢.
medie2005 2009-02-25
  • 打赏
  • 举报
回复
你的快速排序是怎么实现的?按理不会那么慢.
gsymichael 2009-02-25
  • 打赏
  • 举报
回复
我又修改了一下快速排序的方法,好比按由高到低来排序,如果第一次排序之后发现左边的项已经大于10,
这里应该是100,不是10
dzc8866 2009-02-25
  • 打赏
  • 举报
回复
学习了!UP
gsymichael 2009-02-25
  • 打赏
  • 举报
回复
To litaoye:
多谢你的帮助,用数组验证发现的确耗时极短,从几毫秒到20ms,看来使用链表在排序过程中对性能还是会产生很大的影响。
绿色夹克衫 2009-02-25
  • 打赏
  • 举报
回复
比如你在做计数的部分加一个判断,如果计数超过10次,就将该内容推送至cache,为cache定义一个共同的生存周期,比如说30分钟,
用户每次访问cache里面内容的时候,将cache的最新访问时间更新至当前时间。然后定义一个计时器,
每隔10分钟检查一下cache里面的最新更新时间,如果超过30分钟没有访问,则将该记录对应的cache里的内容请空。
比较简单的思路就是这样。如果cache大小有限制,比如100,那么也只需要访问这100个元素,找出更新时间最早的1个。

[Quote=引用 10 楼 gsymichael 的回复:]
To litaoye:
多谢你的回复,我上面的意思是因为数组的下标实际有意义,所以不能直接以数组为目标来做快速排序。那么我就将数组转成一个对应的链表。我感觉使用链表应该比用数组来的慢一些,但是我觉得怎么也不应该到9S。
我的代码也有贴出,我感觉在实现上应该也没有错误。我后面会去直接用数组来试验一下,看看直接用数组时耗时会有多少。
我在生成链表的时候也已经把读次数为0的去掉了,发生过读操作的大约有8700左右个页…
[/Quote]
gsymichael 2009-02-25
  • 打赏
  • 举报
回复
To litaoye:
多谢你的回复,我上面的意思是因为数组的下标实际有意义,所以不能直接以数组为目标来做快速排序。那么我就将数组转成一个对应的链表。我感觉使用链表应该比用数组来的慢一些,但是我觉得怎么也不应该到9S。
我的代码也有贴出,我感觉在实现上应该也没有错误。我后面会去直接用数组来试验一下,看看直接用数组时耗时会有多少。
我在生成链表的时候也已经把读次数为0的去掉了,发生过读操作的大约有8700左右个页。不知道是不是可以用你提到的hash。

还有你建议的那个方法,我感觉是挺不错的。但是有个地方还有些疑问:
就是你提到定时以及刷新这部分,如何来更新时间,能大概说一下实现的思路吗?谢谢!
绿色夹克衫 2009-02-25
  • 打赏
  • 举报
回复
又想了一下这个问题,其实cache的做法调整一下,无论是程序,还是效果都可能更好!
比如凡是计数超过10的,就放入cache中,然后定义一个时间,每次从cache中访问的话,
都更新这个时间,然后每隔固定的时间清理一下超时的cache.
绿色夹克衫 2009-02-25
  • 打赏
  • 举报
回复
如果不想打乱原数组的顺序,那么怎么也得再定义一个数组来做排序,并且将新的数组元素与原数组建立对应的hash关系
这样排序完成之后,你才能知道排在第一的元素对应的是原来的哪个元素。否则光是用程序查找这个对应关系,时间也不短。

我觉得9S是挺长的一个时间,LZ真的应该仔细分析一下,这个时间是否只是由于排序造成的,如果使用了快速排序,
效率由n^2降至了logn,以65535为例,那下降的时间恐怕几十倍,不应该还是9秒,另外LZ可以说一下计数的范围么?

如果范围不大,直接对计数使用hash,会更快!

[Quote=引用 7 楼 gsymichael 的回复:]
To litaoye:
你贴出的方法我试了一下,还是没有能减少排序的时间。

还有你们提出使用快速排序效率应该会很好,不知道是不是我在实际代码中使用的和具体的有差异造成的:
在算法中都是一个一维数组排序,而我使用的数组其下标也有特定函数,用来表示页的号码,这样就不能简单
的直接使用快速排序,不然执行过Swap后页码就搞乱了。所以我会把数组中不为0的项放到一个链表中,链表成员
就可以记录页码和读次数两个值,同…
[/Quote]
gsymichael 2009-02-25
  • 打赏
  • 举报
回复
To litaoye:
你贴出的方法我试了一下,还是没有能减少排序的时间。

还有你们提出使用快速排序效率应该会很好,不知道是不是我在实际代码中使用的和具体的有差异造成的:
在算法中都是一个一维数组排序,而我使用的数组其下标也有特定函数,用来表示页的号码,这样就不能简单
的直接使用快速排序,不然执行过Swap后页码就搞乱了。所以我会把数组中不为0的项放到一个链表中,链表成员
就可以记录页码和读次数两个值,同时在进行swap也不会搞乱页码。但是在操作中比较和交换都没法直接像数组那样
简单的给一个下标就能操作,还需要从链表上循环查询,这样应该也会增加时间,但不知这些多出来的操作会不会浪费
那么多的时间,能使查询过程达到9S。
gsymichael 2009-02-25
  • 打赏
  • 举报
回复
之后我又把QSort修改了一下:

void qsort(int v[], int left, int right, int NeedNum)
  {
  int j, last;
if(NeedNum == 0)
return;
  if (left >= right)
  return;
  swap(v, left, (left + right)/2);
  last=left;
  for (j = left+1; j <= right; j++)
  {
  if (v[j] < v[left])
  {
  swap(v, ++last, j);
  }
  }
  swap(v, left, last);
if(last > NeedNum)  
  qsort(v, left, last-1,NeedNum);
else
  qsort(v, last+1, right,NeedNum-last);
  }

gsymichael 2009-02-25
  • 打赏
  • 举报
回复
我用的快速排序是百度来的,代码如下:

  inline void swap(int v[], int k, int j)
  {
  int temp;
  temp = v[k];
  v[k] = v[j];
  v[j] = temp;
  }
  void qsort(int v[], int left, int right)
  {
  int j, last;
  if (left >= right)
  return;
  swap(v, left, (left + right)/2);
  last=left;
  for (j = left+1; j <= right; j++)
  {
  if (v[j] < v[left])
  {
  swap(v, ++last, j);
  }
  }
  swap(v, left, last);   
  qsort(v, left, last-1);
  qsort(v, last+1, right);
  }

33,028

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧