解决方案 »

  1.   

    你的A线程读取高达300MB/S?那么数据肯定不能放内存了,只能放文件了,那么毫无疑问会占用读写IO带宽了。那么B线程读文件,同样也会占用IO带宽,你说IO竞争的情况下,能保证A线程处理不抖动吗?要么就得加RAID卡,提高硬盘的IO性能,要么提高运算效能,让接受的数据能不在内存中堆积,比如运算放到分布式机器上多台运算。
      

  2.   

    “300MB/S”和“16M的缓存”——也就是说每秒钟至少读取19次
    “一次读取操作差不多需要持续50ms”——基本上A线程一直都在使用资源多线程归根到底也是在同一套硬件上运行的,单核CPU上的多线程只能改良运行效果,根本提高不了运行效率
    即使是多核CPU,由于其他硬件还是同一套,运行效率再怎么提也到不了单线程的2倍综上所述,我认为楼主面临的问题难以用多线程解决。这个问题的本质是“A线程的正常工作需要占用几乎全部计算资源,B线程哪怕使用一点计算资源都会导致A线程工作失常”。
    设法降低数据读取速率或者换更好的硬件吧。通过文件转接就别想了,硬盘读写效率比内存低多了。以上纯属个人意见,如有谬误欢迎指正。
      

  3.   


    说的很有道理呢。但是自己愚钝,有几个地方不太明白,还想请教一下。
    我用的是4核4线程的电脑,跑这个程序基本上就是A、B线程各占一个核(设置了affinity)。按照你的说法就是它们即使各占一核,但是其他软硬件资源都是共享的(如你说的计算资源),所以B线程的复杂计算占用了大量计算资源,导致A线程不能正常工作,出现时错时对的现象。不知我理解的对不对?
    我还想向你请教一个问题,你这里指的计算资源是指?
    之前我以为这个问题是总线的占用造成的,因为看书上说即使是多核,每个CPU的cache到内存只能共享一条总线。然后我把计算中大量开辟空间的语句提到了B线程开始之前,再测试发现有了很大的改善……还想请问这种方法对吗?是不是确实也有总线占用的问题?不好意思……菜鸟一个,问题有点多,谢谢大神了!!!!
      

  4.   

    读取速度高达300MB/S,
    这个是什么样的模式?猝发的?持续的?持续猝发的?
      

  5.   

    如果B线程的执行可以和A线程同步又不在意执行效率的话可以将 B线程不能改成进程嘛。原来的B线程只用作在A线程完成一次读写任务后的给B进程一次通知消息,允许B进程开始读取保存的数据。由系统管理资源分配
      

  6.   


    就是采用多进程的方案?
    那如果如上面大神所说是IO竞争或计算资源不足的问题,这样做还是会影响A线程的吧?
      

  7.   

    1.最好不要不要设置16M的缓冲 改为1M以下的缓冲 设置1M的缓冲队列 队列大小不限 有数据就持续MALLOC
    2.B线程负责处理1M的数据会快很多。如果实在满就1M存数据库或者文件 由B进程处理。
      

  8.   

    你设计个队列缓冲池 一个线程(readandputDataThread)从外部读数据加入队列尾,一个(getandealDataThread)从队列头取出数据,队列元素就限制数据为8000字节以下。在getandealDataThread启动你的计算线程 (TaskThread) 一般大流量都可以解决的。还不行就独立计算进程,在getandealDataThread把数据存储起来。用另外一个计算机用计算线程远程处理。
      

  9.   

    这个内存缓冲池都扛不住你的A线程,很快就得爆掉。
    文件缓冲池我怀疑能否跟得上A线程的速度,磁盘读写有300M/S ?
    有的话就用文件缓冲池吧:内存映射文件 -> 内存映射文件 -> 内存映射文件 -> ...
                 <-            ...            <-如上模式,一个ring buffer。A不断的写,B不断的读和计算。
      

  10.   

    个人觉得B的计算效率很高的话,应该能处理的及A中的数据存取速度,想办法改善B的计算效率
      

  11.   

    时间长了还是得爆掉,你这最根本的问题是A的速度要求太高,B计算的太慢,根本无法调和。B的计算实时性不要求,但要求B无论怎么计算都不能影响A的工作。
      

  12.   

    时间长了还是得爆掉,你这最根本的问题是A的速度要求太高,B计算的太慢,根本无法调和。B的计算实时性不要求,但要求B无论怎么计算都不能影响A的工作。A看起来是I/O型的线程,不怎么耗CPU,可以启动多个B的实例,多线程计算。
      

  13.   


    那我这个其实和你说的类似呀,只是我的队列里只能有两个(读线程),然后由一个计算线程来进行处理,因为我不要求计算的实时性,所以间隔多个数据再计算一次也无所谓。关键是只要有计算,读线程读到的数据就有问题,直观的看就是递增性被破坏了我觉得如果把这些数据写入文件都来得及的话,那处理就应该没有什么问题吧。  如果是接收来不及,串口接收缓冲区溢出的话,那肯定会有错误数据,而且应该会有提示的吧。
    个人觉得还是该先确认数据丢失的原因,确认了原因就好解决了现在就是不知道原因在哪里了。如果没有计算线程的话,是不存在这些问题的。而一有计算线程就出问题了……
    按照你的描述,B线程是CPU密集型,A线程是IO密集型,按理说B线程不太可能会干扰到A线程,即使在老的DMA方式上,大块的数据传输也都是交给DMA控制器去完成的,传输数据的时候总线由DMA控制器控制,CPU这个时候是空闲的。
      

  14.   


    那我这个其实和你说的类似呀,只是我的队列里只能有两个(读线程),然后由一个计算线程来进行处理,因为我不要求计算的实时性,所以间隔多个数据再计算一次也无所谓。关键是只要有计算,读线程读到的数据就有问题,直观的看就是递增性被破坏了我觉得如果把这些数据写入文件都来得及的话,那处理就应该没有什么问题吧。  如果是接收来不及,串口接收缓冲区溢出的话,那肯定会有错误数据,而且应该会有提示的吧。
    个人觉得还是该先确认数据丢失的原因,确认了原因就好解决了现在就是不知道原因在哪里了。如果没有计算线程的话,是不存在这些问题的。而一有计算线程就出问题了……
    按照你的描述,B线程是CPU密集型,A线程是IO密集型,按理说B线程不太可能会干扰到A线程,即使在老的DMA方式上,大块的数据传输也都是交给DMA控制器去完成的,传输数据的时候总线由DMA控制器控制,CPU这个时候是空闲的。复杂计算中包括很多访问各种malloc好的空间,这个会影响么?
      

  15.   

    时间长了还是得爆掉,你这最根本的问题是A的速度要求太高,B计算的太慢,根本无法调和。B的计算实时性不要求,但要求B无论怎么计算都不能影响A的工作。A看起来是I/O型的线程,不怎么耗CPU,可以启动多个B的实例,多线程计算。B不要求实时性,只要给出一个此时读取到数据的示意就可以了。关键在于不能干扰A,因为之后还会增加一个C线程用于A线程读到数据的存储。如果干扰了,那存储下来的都是错误的数据。
      

  16.   

    时间长了还是得爆掉,你这最根本的问题是A的速度要求太高,B计算的太慢,根本无法调和。B的计算实时性不要求,但要求B无论怎么计算都不能影响A的工作。A看起来是I/O型的线程,不怎么耗CPU,可以启动多个B的实例,多线程计算。B不要求实时性,只要给出一个此时读取到数据的示意就可以了。关键在于不能干扰A,因为之后还会增加一个C线程用于A线程读到数据的存储。如果干扰了,那存储下来的都是错误的数据。存储下来的都是错误的数据,可能不关线程的事。
    因为如果是来不及接收的话,数据的结构就肯定不对,比如数据头什么的会丢失,那可能数据就会被抛弃吧。
    那说明是接收到数据后,数据值被改变了。如果是这样,那就可能是算法或者同步的问题了。
    你可以加一些日志,看看是接收到的数据就是错误的,还是接收正确,数据后来出错的。
      

  17.   

    时间长了还是得爆掉,你这最根本的问题是A的速度要求太高,B计算的太慢,根本无法调和。B的计算实时性不要求,但要求B无论怎么计算都不能影响A的工作。A看起来是I/O型的线程,不怎么耗CPU,可以启动多个B的实例,多线程计算。B不要求实时性,只要给出一个此时读取到数据的示意就可以了。关键在于不能干扰A,因为之后还会增加一个C线程用于A线程读到数据的存储。如果干扰了,那存储下来的都是错误的数据。存储下来的都是错误的数据,可能不关线程的事。
    因为如果是来不及接收的话,数据的结构就肯定不对,比如数据头什么的会丢失,那可能数据就会被抛弃吧。
    那说明是接收到数据后,数据值被改变了。如果是这样,那就可能是算法或者同步的问题了。
    你可以加一些日志,看看是接收到的数据就是错误的,还是接收正确,数据后来出错的。
    怎么加日志测试这个问题呢?这个完全没弄过……
      

  18.   


    今天测试了下,我把计算部分屏了,然后用一个上百万级的for循环,内部用了加减乘除和好几个开方,发现效果和有计算是一样样的。看来是计算资源不足引起的吧……具体我也不大明白为什么计算资源不足就造成了断数或者抖动的效果,不过应该能确定是这个问题了。
    如果是这样的话,用多进程也没有太大改善吧?
      

  19.   


    那我这个其实和你说的类似呀,只是我的队列里只能有两个(读线程),然后由一个计算线程来进行处理,因为我不要求计算的实时性,所以间隔多个数据再计算一次也无所谓。关键是只要有计算,读线程读到的数据就有问题,直观的看就是递增性被破坏了我觉得如果把这些数据写入文件都来得及的话,那处理就应该没有什么问题吧。  如果是接收来不及,串口接收缓冲区溢出的话,那肯定会有错误数据,而且应该会有提示的吧。
    个人觉得还是该先确认数据丢失的原因,确认了原因就好解决了现在就是不知道原因在哪里了。如果没有计算线程的话,是不存在这些问题的。而一有计算线程就出问题了……
    按照你的描述,B线程是CPU密集型,A线程是IO密集型,按理说B线程不太可能会干扰到A线程,即使在老的DMA方式上,大块的数据传输也都是交给DMA控制器去完成的,传输数据的时候总线由DMA控制器控制,CPU这个时候是空闲的。复杂计算中包括很多访问各种malloc好的空间,这个会影响么?
    malloc是CRT函数,行为取决于CRT库的实现。在Windows上,它有可能是调用HeapAlloc→VirtualAlloc。当进行DMA的时候,CPU如果也需要访问内存,DMA控制器的优先权一般来说高于CPU,所以CPU执行访存指令不会打断DMA。
      

  20.   


    今天测试了下,我把计算部分屏了,然后用一个上百万级的for循环,内部用了加减乘除和好几个开方,发现效果和有计算是一样样的。看来是计算资源不足引起的吧……具体我也不大明白为什么计算资源不足就造成了断数或者抖动的效果,不过应该能确定是这个问题了。
    如果是这样的话,用多进程也没有太大改善吧?
    去掉B线程,只保留A线程,使用资源管理器观察一下A线程CPU占用率高不高,如果A线程的CPU占用率明显,那你得考虑一下是不是A线程的设计有问题。
      

  21.   


    今天测试了下,我把计算部分屏了,然后用一个上百万级的for循环,内部用了加减乘除和好几个开方,发现效果和有计算是一样样的。看来是计算资源不足引起的吧……具体我也不大明白为什么计算资源不足就造成了断数或者抖动的效果,不过应该能确定是这个问题了。
    如果是这样的话,用多进程也没有太大改善吧?
    去掉B线程,只保留A线程,使用资源管理器观察一下A线程CPU占用率高不高,如果A线程的CPU占用率明显,那你得考虑一下是不是A线程的设计有问题。我现在没有写硬盘的操作,应该就没有DMA吧?
    另外,B线程是不能去掉的,去掉就没啥好显示的了。A线程也不能够停止否则数据会被截断,所以A线程的CPU占用率是100%,但是我已经固定它在一个核上了,我的主板是4核4线程的。是不是因为3楼说的,计算资源的问题造成了A线程占用几乎所有资源,导致在不影响A的情况下B线程的可用资源很少??但是我奇怪的就是,A线程中没有进行任何计算,就是一个驱动封装好的读函数的调用,和一个事件对象的启动,如此循环往复,这哪里占用计算资源了??
      

  22.   


    今天测试了下,我把计算部分屏了,然后用一个上百万级的for循环,内部用了加减乘除和好几个开方,发现效果和有计算是一样样的。看来是计算资源不足引起的吧……具体我也不大明白为什么计算资源不足就造成了断数或者抖动的效果,不过应该能确定是这个问题了。
    如果是这样的话,用多进程也没有太大改善吧?
    去掉B线程,只保留A线程,使用资源管理器观察一下A线程CPU占用率高不高,如果A线程的CPU占用率明显,那你得考虑一下是不是A线程的设计有问题。我现在没有写硬盘的操作,应该就没有DMA吧?
    另外,B线程是不能去掉的,去掉就没啥好显示的了。A线程也不能够停止否则数据会被截断,所以A线程的CPU占用率是100%,但是我已经固定它在一个核上了,我的主板是4核4线程的。是不是因为3楼说的,计算资源的问题造成了A线程占用几乎所有资源,导致在不影响A的情况下B线程的可用资源很少??但是我奇怪的就是,A线程中没有进行任何计算,就是一个驱动封装好的读函数的调用,和一个事件对象的启动,如此循环往复,这哪里占用计算资源了??
    1,你对DMA的理解完全不对,你的外部硬件设备的驱动决定了用什么方式进行IO,如此大数据量的传输,不使用DMA是难以想象的;
    2,假设驱动使用DMA方式传输数据,且A线程没有复杂计算的话,100%的CPU占用是不合理的;
    3,全方位使用资源管理器观察A线程,尤其是其Kernel Time;
    4,如果B线程仅仅是显示一些东西在UI上的话,为何不能暂时屏蔽掉?只运行A线程,通过Resource Monitor观察其主要CPU资源都消耗在哪,先排除是不是A线程、外设驱动的设计问题。
      

  23.   


    今天测试了下,我把计算部分屏了,然后用一个上百万级的for循环,内部用了加减乘除和好几个开方,发现效果和有计算是一样样的。看来是计算资源不足引起的吧……具体我也不大明白为什么计算资源不足就造成了断数或者抖动的效果,不过应该能确定是这个问题了。
    如果是这样的话,用多进程也没有太大改善吧?
    去掉B线程,只保留A线程,使用资源管理器观察一下A线程CPU占用率高不高,如果A线程的CPU占用率明显,那你得考虑一下是不是A线程的设计有问题。我现在没有写硬盘的操作,应该就没有DMA吧?
    另外,B线程是不能去掉的,去掉就没啥好显示的了。A线程也不能够停止否则数据会被截断,所以A线程的CPU占用率是100%,但是我已经固定它在一个核上了,我的主板是4核4线程的。是不是因为3楼说的,计算资源的问题造成了A线程占用几乎所有资源,导致在不影响A的情况下B线程的可用资源很少??但是我奇怪的就是,A线程中没有进行任何计算,就是一个驱动封装好的读函数的调用,和一个事件对象的启动,如此循环往复,这哪里占用计算资源了??
    1,你对DMA的理解完全不对,你的外部硬件设备的驱动决定了用什么方式进行IO,如此大数据量的传输,不使用DMA是难以想象的;
    2,假设驱动使用DMA方式传输数据,且A线程没有复杂计算的话,100%的CPU占用是不合理的;
    3,全方位使用资源管理器观察A线程,尤其是其Kernel Time;
    4,如果B线程仅仅是显示一些东西在UI上的话,为何不能暂时屏蔽掉?只运行A线程,通过Resource Monitor观察其主要CPU资源都消耗在哪,先排除是不是A线程、外设驱动的设计问题。

    好的,我先按照你说的方法试试看,谢谢你的指导!!!要是还有问题再来请教你!!
      

  24.   

    楼上说的好。。读写硬盘不计算怎么都不可能点用整个CPU核心。。用读写测试硬盘软件很多了。。高时也就10%上下。。看来是这个问题,,,看了这么多人回复。。个人愚见。。A读取量大。。B处理不够快。。早晚要暴掉的,,所以。。楼上的某楼不是说了。。只开一条线程读取。多线程多核心计算。。以达到平衡,,
      

  25.   


    今天测试了下,我把计算部分屏了,然后用一个上百万级的for循环,内部用了加减乘除和好几个开方,发现效果和有计算是一样样的。看来是计算资源不足引起的吧……具体我也不大明白为什么计算资源不足就造成了断数或者抖动的效果,不过应该能确定是这个问题了。
    如果是这样的话,用多进程也没有太大改善吧?
    去掉B线程,只保留A线程,使用资源管理器观察一下A线程CPU占用率高不高,如果A线程的CPU占用率明显,那你得考虑一下是不是A线程的设计有问题。我现在没有写硬盘的操作,应该就没有DMA吧?
    另外,B线程是不能去掉的,去掉就没啥好显示的了。A线程也不能够停止否则数据会被截断,所以A线程的CPU占用率是100%,但是我已经固定它在一个核上了,我的主板是4核4线程的。是不是因为3楼说的,计算资源的问题造成了A线程占用几乎所有资源,导致在不影响A的情况下B线程的可用资源很少??但是我奇怪的就是,A线程中没有进行任何计算,就是一个驱动封装好的读函数的调用,和一个事件对象的启动,如此循环往复,这哪里占用计算资源了??
    1,你对DMA的理解完全不对,你的外部硬件设备的驱动决定了用什么方式进行IO,如此大数据量的传输,不使用DMA是难以想象的;
    2,假设驱动使用DMA方式传输数据,且A线程没有复杂计算的话,100%的CPU占用是不合理的;
    3,全方位使用资源管理器观察A线程,尤其是其Kernel Time;
    4,如果B线程仅仅是显示一些东西在UI上的话,为何不能暂时屏蔽掉?只运行A线程,通过Resource Monitor观察其主要CPU资源都消耗在哪,先排除是不是A线程、外设驱动的设计问题。

    好的,我先按照你说的方法试试看,谢谢你的指导!!!要是还有问题再来请教你!!
    由于各种杂事又搁置了好久……希望大神还能依稀记得。
    目前这个驱动是用DMA的方式,但是是查询的工作方式,而每次又只有16K的数据传输,所以导致CPU的占用率很高。
    那如果我想做到A读取,B计算,C存储三个线程并行且能正常工作,要怎么去弄呢?把DMA改成中断的工作方式可以吗?