65.9K
CodeProject 正在变化。 阅读更多。
Home

Rogue Wave CodeDynamics:评论

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2015年11月17日

CPOL

7分钟阅读

viewsIcon

13169

我对 Rogue Wave 的 CodeDynamics 产品进行深入研究,是为了解决我从大学时代就一直面临的一个挑战:调试遗传算法 (GA) 应用。

通常,当我测试新的软件开发或 IT 运维工具时,我都是出于工作需要。但这一次,我有一个萦绕心头的老难题需要解决,而一款现代化的工具最终提供了解决方案。我对 Rogue Wave 的 CodeDynamics 产品进行深入研究,是为了解决我从大学时代就一直面临的一个挑战:调试遗传算法 (GA) 应用。

我决定重新审视我尘封已久的 GA API,这源于我在加利福尼亚州利弗莫尔的一家共享办公空间与同行们的一次谈话。虽然我主要开发营销应用程序,但我的创业伙伴们在研究激光和 DNA 条形码。因此,与他们相比,我对自己代码库感到有些自卑。其中一家同行公司正在研究量子密码学。于是,我开始思考,要构建更优秀的加密解密软件,能够抵御未来的量子计算机,需要什么样的计算能力?以及如何才能实现这样的程序?

然而,这类应用程序的真正问题在于,即使是最简单的算法以海量规模运行时,也会出现有趣的调试挑战。要以规模化方式运行此类应用程序的唯一方法是使用大量进程和大量线程。但当出现问题时,应用程序在所有这些工作线程上的分布式特性使得弄清楚问题出在哪里变得非常困难。而 GA 应用相对简单,并且在多代、多群体(线程)包含许多“生物体”的迭代中运行效果最佳。

GA 从达尔文的进化论中汲取了一些灵感。基本上,你构建一个应用程序,它包含一个生态系统、生物体以及它们生存、死亡和繁殖的规则。你随机生成这些生态系统,并在计算机速度下让它们迭代多次。规则由所谓的“适应度函数”决定。适应度函数为每个生物体分配一个分数,表明它们在解决某个“问题”方面的适应程度。

我决定可以使用 GA 来进化加密算法,同时通过模拟解密算法来测试加密的强度。这很巧妙之处在于,它们可以互相充当对方的适应度函数。但这需要大量的群体实例。为了做到这一点,需要测试各种生态系统变量。

我设计了我的应用程序,其中一个进程对应一个生态系统线程。你可以保持简单,一次只有一个生态系统,但正如你稍后会看到的,构建多个是有好处的。这不是为了速度,因为你想测试生态系统的许多变量,以找出最能产生最佳结果的变量。你看,GA 的问题在于它是一个黑箱。即使你得到了一个结果(一个能够解决适应度函数的超适应个体),你也无法知道它是如何实现的。而且你不一定知道那是否是最有效的方法。虽然你可以玩转死亡率甚至疾病等生态系统变量,但这 all 只是猜测游戏,是一种不太科学的改进应用程序的方式。

最后,这就是 CodeDynamics 发挥作用的地方。该工具源于超级计算机调试的基础,这使其非常适合管理和调试高度分布式的应用程序。凭借 CodeDynamics 独特的调试、暂停和回放功能,我终于能够以更审慎的方式解决变量挑战。CodeDynamics 将允许我深入黑箱,更好地了解最终输出是如何产生的。

我没有使用我旧的 GA 代码库,而是使用了来自 MIT 的一个经过更充分验证的库,并添加了一些生态系统函数,例如“疾病”。我编写了我的应用程序,它进化了神经网络加密器,而适应度函数是一个类似进化的解密器。这样做很有趣,因为我同时进化了加密和解密,但对于实际的加密来说并非最佳方法。

我首先在 Mac 的 Xcode 中编译了应用程序,然后将二进制文件移动到我的 Linux 服务器。之后,我就可以在 CodeDynamics 中直接打开并运行该应用程序了。或者,我也可以直接运行应用程序,然后将 CodeDynamics 附加到该进程上。

CodeDynamics 中的所有操作都像 DVD 播放器一样(要查看设置教程,请访问此 页面)。除了播放,最让我兴奋的是暂停按钮。就执行而言,它相当直接,有一个树状结构供你查看线程,然后你可以深入到问题的所在,或者在我的情况下,是你关注的区域。一旦你这样做,你就可以获得关于线程/进程及其运行变量的详细信息。

后来我发现,用于反向调试的 ReplayEngine 对我来说将更有价值。如果我记录应用程序的每次运行,那么我就不需要像盯着老鹰一样盯着它,或者预估需要暂停多少代才能检查结果。相反,我可以记录整个过程,然后反向进入似乎具有最有益结果的群体,以查看哪些环境变量对适应度贡献最大。

它允许我做的另一件疯狂的事(以前我做不到的)是允许群体之间的繁殖——因此也允许线程之间的繁殖。我可以实现这一点,但要以一种系统的方式来了解其影响,甚至了解它是否正确发生,将会非常困难。

现在,比赛开始了。我不得不将我的代数限制在一个合理的范围内,以便快速聚焦于变量。解密速度相当慢。然后,一旦我认为我走上了正确的轨道,我就可以进行更大规模的运行。果不其然,当我开始使用该工具时,我能够聚焦于那些似乎最有用的变量。直到……我意识到我的适应度函数实际上引入了一个问题,该问题阻止了收敛到局部最大值之外。

一旦我准备就绪并开始运行,就很简单了。但我也遇到了一些减缓我进度的障碍。首先是理解我在 CodeDynamics 中可以做什么,与直接在 Xcode 或 Visual Studio 中可以做什么之间的区别。虽然你可以深入到进程,但对堆栈的访问是有限的。就我个人而言,除非我非常聪明地设置断点,否则我无法看到影响我代码的生态系统变量。它还更好地指示了我的某个群体是否完全崩溃,但这并不明显,因为它们仍然返回了一个结果。

以下是我在过程中遇到的一些其他磕磕碰碰

  • 我不再是 C++ 开发者了。现在我主要用 C# 和 Java 编程。我很希望看到对这些语言提供更多支持。同样,我也非常希望看到 Windows 和 Mac 版本。
  • 拥有两个独立的工具,一个 IDE 和一个调试器,这对我来说并不熟悉。但一旦我习惯了它,并且组织好我的构建,也就好了。
  • 该产品相对较新,但我希望能看到关于如何使用该工具的视频,因为在熟悉它并能轻松使用之前需要一段时间。
  • 最后,如果他们能想办法实现线程命名或更好地标识线程,那就更好了。编号系统使得很难知道该看哪里。

总之,在我重新焕发活力之后,我一直在利用我过去的 GA 开发经验来构建除加密之外的其他有趣应用程序。现在我正利用 GA 来帮助构建自然语言处理 (NLP) 在大量业务文档中产生的实体的异常检测算法。这是一个更实际的问题。

除了重新拾起一个旧的爱好并解决调试分布式应用程序的老问题之外,我还能够实现以前只敢梦想的功能。我的特殊情况可能有些独特,但存在大量应用程序隐藏在进程和线程的迷宫中,存在灾难性 bug 或性能问题,我相信像 Rogue Wave CodeDynamics 这样的调试工具至少可以帮助创建更高效的代码。

© . All rights reserved.