parfor, callback, real-time data reading

rossubscriber和parfor一起用的时候,风味独特。
经测试,
在release mode的时候,parpool的正在启动的时候,rossubscriber会使用callback不断地读入信息,而一旦parpool成功开启(这个时间节点很重要),callback似乎就停止下来了不再读取新信息。所有数据更新停留在parpool成功开启的那个时间点。当然,这是在parpool语句放在rossubscriber语句之后,才可以发生的,若parpool语句在rossubscriber之前,则parpool在callback运行前开启完毕,callback根本没有机会读取新信息。
然而,当在debug mode的时候,这些问题不会发生。
由此,做出以下猜想:当parpool启动完毕的时候,两个core都被占用了并且变成忙的状态,因此没有剩余的计算资源供callback使用了。但是在debug mode的时候,core可以切换回空闲状态,因此有计算资源可供callback使用。

好,用这个思路来尝试解决这个问题。
1. 查阅matlab在debug mode下的相关配置信息,是否验证了我的猜想。好吧,查不到。。。
2. 在开启parpool的时候,开启少于系统最大数量的个数。例如,电脑是双核电脑,最大数量可以是2,但是我们现在只开启一个parpool(1),来看剩余的那个计算资源可否被使用到callback上。经测试,发现并没有帮上忙。。。
3. 既然2的方法不奏效,那么极有可能是,空闲的资源并不能被自动运用于robotic toolbox system的运算,那么尝试指定计算资源给robotoic toolbox system可不可以呢?
(1)使用batch job. 为了可以让callback在后台工作,将wrenchhandle = rossubscriber(‘robot/../../endpoint_state’,@wrenchCallback)语句放进wrench_callback_script里,然后在原文件中用job= batch(‘wrench_callback_script’)代替。实践发现,load(job,’wrenchhandle’)是非法的。rossubscriber对象不可以被load。。。可是不load似乎又没有在后台运行callback啊。。。改了这个之后比之前更糟糕。
(2)使用spmd. 估计会和parfor,parpool一样的结局。
4. 前面的方法都不奏效,那也可能的确不是parpool引发的问题。。。所以,直接用for来试试,将所有的并行计算改成for运算,发现问题依然存在!!!而且更严重,callback甚至根本不更新不读取新信息!!!说明,这并不是parpool造成的问题,必定是callback造成的问题。然而在debug mode依然是可以成功运行的。。。不知道该如何面对。用Ctrl-c来终止程序的时候,反而触发了callback读取了三两个新信息。。。好的,赶紧在mathwork里查询matlab里面的Ctrl-c的机制:为什么他可以触发callback?然后,找到了一个答案,网址是:http://www.mathworks.com/matlabcentral/answers/101348-why-is-ctrl-c-inconsistent-in-breaking-out-of-loops-in-matlab-7-0-r14
5. 在这个答案里,说明在每一个loop里面需要加入drawnow可以促使程序将计算队列里面的工作做完,怀着死马当活马医的心情,我在loop的end前添加一句“drawnow”,麻木地按下了运行键,发现可以成功运行了。



!!!可以成功运行了!!!目瞪口呆.jpg
再查询drawnow的帮助,看看它为什么可以解决我的问题:

help drawnow
drawnow Update figure windows and process callbacks

天都光嗮。。。这说明了,每一个细节都可能是珍贵的症状信息,可以指引你发现问题所在,帮助你查到解决方法,虽然很多时候都不是真正有用的症状信息,但是不要轻易放弃细节!
————————2016.4.20 的分割线——————————————-

————————2016.7.4发现的———————-
以下是可以正常实时读取数据的代码:
delete(gcp);
parpool(2);
while(){
parfor…
drawnow;
}
以前以为是有drawnow才可以让程序正常实时读取数据,但是后面发现,没有开启parpool的话,即使有drawnow, globalIndex也根本更新不了,实时数据一个也读取不到。如果开启了parpool,但是没有在循环内使用parfor的话,globalIndex只能在parpool启动时的那段时间得到更新,后面就不能继续更新了。。。
为什么只有parpool的开启可以让callback工作呢。。。

### 关于并行循环 (Parfor) 的用法 `parfor` 是 MATLAB 中用于实现并行计算的一种工具,它允许用户通过简单的语法编写并行化的 `for` 循环。这种功能特别适用于那些可以分解成独立子任务的大规模数据处理或复杂算法设计场景。 #### Parfor 基本概念 在 MATLAB 和类似的框架中,`parfor` 提供了一种简单的方式来利用多核处理器的能力来加速程序运行时间。与传统的 `for` 循环不同的是,`parfor` 将迭代分配给多个工作线程执行[^1]。这意味着如果硬件支持足够的并发能力,则每次迭代都可以由不同的核心同时完成。 以下是几个需要注意的关键点: - **变量分类**: 使用 parfor 时需注意区分切片变量(sliced variables),广播变量(broadcasted variables),以及临时变量(temporary variables). - **依赖关系管理**: 如果存在跨迭代之间的相互依赖(即当前迭代的结果取决于前一次或其他任意次迭代),那么这些依赖可能会破坏 parfor 正常运作逻辑. #### 示例代码展示如何正确使用MATLAB中的parfor结构: ```matlab % 初始化一个矩阵A作为输入数据源. n = 100; A = rand(n); % 创建另一个存储结果的零初始化数组B. B = zeros(size(A)); % 开始定义我们的parfor循环体. parfor i=1:n % 这里我们假设每一列都是完全独立的操作对象. B(i,:) = someFunction(A(:,i)); end ``` 上述例子展示了怎样在一个二维随机数阵列上应用函数someFunction()到每列表达式之中,并且由于各列之间不存在任何交互作用所以非常适合采用parfor形式加以优化性能表现. #### 错误案例分析及解决方案建议 当尝试将标准串行流程转换为平行版本时经常会出现错误情况之一就是违反了之前提到过的关于共享状态的规定——具体来说就是在同一个范围内修改全局或者外部范围内的某些特定类型的值可能导致不可预测的行为发生. 例如下面这个不恰当的例子试图更新累积求和sumValue的同时也进行了局部赋值操作x[i]: ```matlab totalSum = 0; parfor idx = 1:length(x) totalSum += x[idx]; y(idx)=f(x[idx]); end ``` 针对这种情况应该考虑重构代码使其满足无副作用的要求,比如把累加器移入内部单独声明从而消除潜在冲突风险如下所示: ```matlab partialSums=zeros(1,numlabs); parfor labIndex=drange(1:numlabs) startIdx=(labIndex-1)*chunkSize+1; stopIdx=min(labIndex*chunkSize,length(x)); partialSums(labIndex)=sum(x(startIdx:stopIdx)); end globalTotal=sum(partialSums); ``` 这里采用了分块策略先分别统计各个片段贡献再汇总得到最终答案有效规避了竞态条件带来的隐患.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值