`
searun
  • 浏览: 176575 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

在OMNeT++中如何有效地使用EV来输出

阅读更多

这是Andras发表的一篇在OMNeT++中如何使用EV来有效的输出日志信息的文章。原网址在http://www.omnetpp.org/article.php?story=20040804203301352

 

译者注:现在的 OMNeT++4.0 已经将这里的结果集成了进去,推荐使用 EV 来输出日志信息。具体的定义见 include/cenvir.h 文件。这篇文章详细的讨论了如何设置 EV ,具有普遍的借鉴作用。

 

ev<< 语句可以用来打印信息从而了解到仿真模型正在做什么。这在进行调试和理解模型运行的时候是很有用的。现在的问题是,当模型需要运行很长时间的时候, ev<< 语句将会消耗大量的 CPU 周期。这个时候该怎么办呢?

 

本文将介绍如何高效率的进行记录,并且同时介绍如何创建 log channels 或者调试 channels

 

Cmdevn 环境下,当设置 express-mode=true 的时候,输出将会被丢弃而不会被打印,从而使得执行可以更快。但是实际上, ev<< 语句还是会带来一些开销。这种速度的减小可能不会被注意到,但是影响却是很大的。这里的问题是, OMNeT++ 将只会丢弃也就是不打印已经转换为文本格式的字符串。举个例子,如下面的语句:

ev << "Average bit/sec is: " << totalBits/simTime() << "n";

 即使是在极速模式下, simTime() 将会被调用,浮点数除法也会被执行。结果将会被转换为字符串并存储在缓冲区中,而这里的缓冲区则会被丢弃。很遗憾的是, OMNeT++ 核心没有办法阻止这种事情发生,因为这是 C++ 的工作方式。

这时候该怎么办呢?一种常见的方式是采用 #ifdef

#ifdef DEBUGGING
ev << "Average bit/sec is: " << totalBits/simTime() << endl;
#endif

这并不坏,但是却有一个很严重的问题:在切换打印输出的时候必须重新编译所有的文件。根据墨菲定律(有可能出错的事情,就会出错,Anything that can go wrong will go wrong),当人们需要输出的时候往往看不到有输出。另外,代码中满含有 #ifdef 也不是一个好办法。随后想到的就是如何在编译的时候就将是否输出考虑到,下面是一个示例代码。

if (debugging)
    ev << "Average bit/sec is: " << totalBits/simTime() << endl;

这比前面要好一些。 if 语句的开销是比较小的。这样,就可以在初始化的时候通过 debugging 变量来决定是否输出信息。

debugging = par("debugging").boolValue();

  这种做法还不是很方便,因为我们需要手工维护输出的状态。有些人会发现此值可以在调试中进行动态设置,但是这还不能令人满意。为什么不能让代码知道我们是否需要记录呢?

实际上,我们可以回答这个问题。一般的, OMNeT++ 知道我们何时需要进行记录:不在极速模式下的时候。幸运的是, ev 对象可以知道这点,所以现在最新的代码如下。

if (!ev.disabled())
    ev << "Average bit/sec is: " << totalBits/simTime() << endl;

 

  几乎就是这样了。现在的问题是需要为每个 ev 输出增加一个 if 语句。有经验的 C/C++ 程序员将会马上想到采用宏来产生精炼的代码。第一次尝试:

#define EV   if (!ev.disabled()) ev    // *** DANGEROUS!***
...
EV << "Average bit/sec is: " << totalBits/simTime() << endl;

  注意,这里的宏将会产生很严重的问题。考虑一下下面的代码:

if (totalBits>1000)
    EV << "Average bit/sec is: " << totalBits/simTime() << "n";
else
    EV << "Not enough data yet" << endl;

  这段代码并不会按照设想的那样工作。当我们宏替换完成并重新缩进代码后,将得到下面的代码:

if (totalBits>1000)
    if (!ev.disabled())
        ev << "Average bit/sec is: " << totalBits/simTime() << endl;
    else if (!ev.disabled())
        ev << "Not enough data yet" << endl;

  所以这里的代码将永远不会打印出“ Not enough data ”。

 

最好是忘记上面的 EV 定义,因为这很容易会使得你栽在上面。即使是在这个宏定义中加上一对括号也不能解决问题,因为打印参数将会在括号之外。看起来这个问题没法修复。

尽管如此,让我们来看看下面这个版本:

#define EV   ev.disabled() ? ev : ev
...
EV << "Average bit/sec is: " << totalBits/simTime() << endl;

  这看起来有点奇怪。这里的宏定义看起来没有区别(无论是为 true 或者是 false ),而且这和所有 C 语言教科书中所倡导的(宏如果需要扩展成表达式需要加上圆括号)相违背。但是确实这个宏是可以工作的。现在 EV<< 将会变成一个简单的表达式。

 

ev.disabled() ? ev : ev << "Average bit/sec is: " << totalBits/simTime() << endl;

  这和下面的相同(注意符号的优先级) :

 

ev.disabled() ? ev : (ev << "Average bit/sec is: " << totalBits/simTime() << endl);

  这时候,当 ev 被禁止的时候(条件为 true ),这只是简单的一个 ev 对象的引用(这最终将会被编译器所优化,而不会产生任何的 CPU 指令);当 ev 启用的时候(条件为 false ),将会被还原成原始的 ev<< 语句。这正是我们所需要的。证明这里的 EV 定义在任何使用场景中都是可行的,这可以作为练习。无论是否有 if 语句,或者是还有一个 ?: 操作符,或者是其他的场景,这都是适用的。

实际上,上面 EV ?: 版本并不能在 VC++ 7.0 中通过编译(因为在 VC++ 7.0 中需要?:三元操作符的第二个和第三个参数的类型是一样的,而不会做默认的转换)。所以在 VC7 中的版本是这样的:

#define EV   ev.disabled() ? (std::ostream&)ev : ev

 (译者注:实际上,由于现在最新的 OMNeT++ 4.0 并不支持使用 VC 编译器进行编译,所以也没有采用这样的方式)。

 

如果你没有用过 log4j 或者是 C++ 中类似的工具( log4Cpp libCWD 等),那你有可能错过调试管道或者说是日志管道。简单地说, channels 是针对快速滚动日志问题的答案(因为你几乎不可能在日志的海洋中找到有用的信息)。你的代码日志将会记录到多个管道中,而在调试的时候可以只关注自己感兴趣的管道。有两个标准可以用来区分管道日志: topic 和调试级别(如 detail, info, warnings )。其中第三个标准是位置(模块位置),这已经被 OMNeT++ 内置了。可以通过查看模块的输出来得到你想要的信息。

一个比较好的消息是通过上面的 EV 定义,可以用来简单的模拟日志管道。当书写一个 IP 模块的时候,检查下面的定义:

#define fwdingEV   (ev.disabled()||!fwdingChannel) ? (std::ostream&)ev : ev
#define localEV    (ev.disabled()||!localChannel) ? (std::ostream&)ev : ev
#define mcastEV    (ev.disabled()||!mcastChannel) ? (std::ostream&)ev : ev
#define dropEV     (ev.disabled()||!dropChannel) ? (std::ostream&)ev : ev

上面的定义提供了四个日志信道( wdingEV, localEV, mcastEV, dropEV ),可以通过单独设置 fwdingChannel, localChannel, mcastChannel, dropChannel 布尔变量的值来进行开关。可以像下面这样使用日志管道。

...
EV << "packet received" << endl;
...
if (destAddress.isMulticast())
{
    mcastEV << "multicast packet, addr=" << destAddress << endl;
    ...
}
...
if (!routeFound)
{
    dropEV << "unroutable packet, dropping" << endl;
    delete datagram;
}
...
 

 

分享到:
评论

相关推荐

    无线传感器网络仿真+基于Omnet++_omnet++mac_omnet_omnet++_deathioo_

    在提供的压缩包中,"无线传感器网络仿真+基于Omnet++_omnet++mac_omnet_omnet++_deathioo_.doc"文件很可能包含了关于如何配置和运行WSN MAC层协议仿真的详细步骤、模型描述和结果分析。阅读这份文档将有助于深入理解...

    omnet++ 中文 使用手册

    通过深入学习和实践这份“Omnet++ 中文使用手册”,用户能够熟练地运用Omnet++进行各种复杂的系统仿真,无论是学术研究还是工业应用,都能得心应手。同时,持续关注社区动态和更新,能保持对Omnet++最新特性和技术的...

    OMNeT++安装及IDE使用教程.pdf

    通过以上步骤,用户可以顺利完成OMNeT++的安装,并掌握如何使用OMNeT++ IDE来进行网络仿真的基本操作。这些教程不仅适用于初学者,也适合那些希望深入探索OMNeT++功能的进阶用户。随着实践的深入,用户还可以进一步...

    OMNeT++4.1中文使用手册

    - 在学术和非盈利性活动中免费使用OMNeT++。 - 进行商业性研究时需要从Global公司获得OMNeST许可证。 通过以上内容的详细介绍,我们可以了解到OMNeT++不仅是一款强大的网络模拟工具,而且具备高度的灵活性和扩展性,...

    omnet++中文手册

    总之,“omnet++中文手册”是一个全面的学习资源,涵盖了Omnet++从基础到高级的所有重要概念,对于想要深入学习和使用Omnet++的人来说是宝贵的参考资料。通过仔细阅读和实践,用户可以掌握Omnet++的核心技术和方法,...

    omnet++中文使用手册

    Omnet++是一款强大的开源模拟器,特别适用于网络和分布式系统的研究与开发。这份"Omnet++中文使用手册"是为那些想要深入理解和高效利用Omnet++的用户...在学习过程中,不断实践和总结,是提高Omnet++使用技巧的关键。

    OMNET++ 详细介绍ppt

    在实际应用中,OMNeT++可以用于模拟各种网络协议,评估网络设计的性能,以及研究网络技术的创新。它可以模拟从局域网到广域网、从有线到无线、从固定到移动的多种网络环境。 总而言之,OMNeT++是一个功能强大且灵活...

    AODV.zip_AODV Omnet++_AODV omnet_omnet_omnet aodv_omnet++

    总的来说,这个AODV的Omnet++实现是一个宝贵的教育资源,有助于学术研究者和工程师理解AODV的工作原理,并对其在实际无线网络中的表现进行评估和优化。通过使用这个工具,我们可以深入探讨路由协议对网络性能的影响...

    OMNET++教程中文

    OMNET++是一种面向对象、模块化和可扩展的离散事件仿真框架,广泛应用于通信网络、多处理器系统、分布式系统等领域的...对于那些致力于无线传感器网络、网络仿真及OMNET++的使用者来说,这份资料是极具价值的参考资料。

    基于omnet++的leach协议的仿真研究

    作者通过结合多帧通信策略,优化LEACH算法,并在omnet++仿真环境中验证了这些改进措施的有效性。 #### omnet++平台介绍 omnet++是一个高性能、开源的离散事件仿真框架,特别适用于通信网络的研究与教学。它提供了...

    OMNeT++文档(一些问题的解决方法)

    本书主要针对使用OMNeT++进行无人机蜂群网络仿真的开发者,作者在学习和实践中积累了丰富的经验,并从官方手册中提炼出常用接口的详细说明,旨在为初学者提供一份实用的入门指南。作者强调,由于个人理解的局限性,...

    Omnet++教程PDF版

    总结来说,"Omnet++教程PDF版"是一份全面的学习资源,无论你是对无线传感器网络感兴趣,还是希望深入理解Omnet++的模拟技术,都能从中受益。通过这份中文教程,你将能够掌握Omnet++的核心功能,提升你的网络建模和...

    OMNet++ 4.1 中文手册PDF

    - **第3、4、6章**:编程指南,介绍NED语言、模拟概念及其在OMNet++中的实现,指导如何编写简单的模块并描述类库。 - **第9、11章**:深入探讨如何定制网络图、编写NED源代码注释等高级主题。 - **第7、8、10章**:...

    OMNET++中文使用手册

    - **第3章、第4章和第6章**:编程指南,讲解NED语言、模拟原理及其在OMNeT++中的应用,以及如何编写简单的模块。 - **第9章和第11章**:深入探讨网络图的定制方法,以及如何编写NED源代码注释。 - **第7章、第8章和...

    基于OMNET++的模拟无线移动网络

    **MiXiM**(Mixed Mobility and Interference Model)作为一款专门针对无线移动网络仿真的扩展框架,它极大地丰富了OMNET++的能力。MiXiM不仅提供了细致的无线通道模型,还涵盖了移动性模型、障碍物模型及多种通信...

    omnet++下仿真100个节点的路由协议

    在本文中,我们将深入探讨如何使用OMNeT++进行无线传感器网络(WSN)的仿真,特别是关于100个节点间的路由协议。OMNeT++是一个强大的开源C++建模和仿真框架,广泛用于通信网络、分布式系统、嵌入式系统和其他复杂...

    OMnet++学习全书

    语法方面,OMnet++使用NED(Network Description)语言来定义网络结构和组件行为,结合C++用于编写更复杂的模块逻辑。 #### 1.2 物理层仿真(信道) 物理层仿真关注的是数据传输的物理媒介,如无线电波或光缆。在...

    OMNET++4.0的入门介绍

    - 成功安装后,可以通过在`mingwenv.cmd`中输入`OMNETPP`命令来启动OMNET++4.0 IDE。 3. **启动OMNeT++4.0**: - 打开OMNeT++安装目录下的`mingwenv.cmd`,并在弹出的命令行界面中输入`omnetpp`以启动软件。 - ...

Global site tag (gtag.js) - Google Analytics