罗兰谈MATLAB的艺术

将想法转化为MATLAB

并行地从Web API获取数据

我来介绍一下本周的客座博主Edric埃利斯.Edric就职于the MathWorks的并行计算开发团队。在这篇文章中,他将谈论如何使用parfeval命令在并行计算工具箱。

在R2013b版本中,我们引入了一个新函数parfeval到并行计算工具箱,允许您在并行池中的工作上运行MATLAB®函数,而不会阻塞桌面MATLAB。这允许您创建比使用这两种方法都更松散的并行程序parforspmd.您还可以让您的桌面MATLAB处理可用的结果,允许您创建更多交互式并行程序。

我们来看看如何使用parfeval通过并行地发出多个请求,然后在每个结果可用时立即显示,从而加快访问web服务的速度。我们要查询Flickr图像共享站点,用于提供与之相关的结构化数据的天文图像。我们将分三个阶段来解决这个问题:

  1. 查询相关图像的web服务
  2. 使用parfeval向并行工作人员提交工作以读取图像
  3. 使用fetchNext检索结果,然后显示它们。

内容

查询相关图像的web服务

Flickr提供了一个基于web的API,允许您查询其庞大的图像数据库。要使用API,您需要向他们的服务器提交一个结构化查询,然后返回一个XML文档。从Flickr检索结果图像数据需要一些时间,通过并行执行检索可以更快地运行。这是一个例子“I / o密集型”操作。

Flickr web API有完整的文档在这里.要使用该API,您需要一个Flickr帐户请求一个'API Key'它包含在对API的每个请求中。一旦你有了自己的键,你就可以把它放在一个叫做flickrApiKey它只是将键作为字符串返回。

appKey = flickrApiKey;

构建搜索URL并解释XML响应

我们将搜索具有特定标签的图像:astrometrydotnet:状态=解决.这些图片被提交到Flickr组,然后astrometry.net分析和注释图像。我们建立一个搜索url,然后让xmlread从该URL读取结果。

Url = [“http://api.flickr.com/services/rest/”...API基础URL”?方法= flickr.photos.search '...% API方法“api_key = 'appKey,...%我们的API密钥'标签= astrometrydotnet % 3 astatus % 3 dsolved '...%标签搜索“许可= 4”...%知识共享“那种= interestingness-desc”...排序顺序“&per_page = 12”...将结果限制为12个“与媒体=照片”];只返回照片Response = xmlread(url);从文档中获取所有的“photo”元素。photos = response.getDocumentElement.getElementsByTagName(“照片”);numPhotos = getLength(photos);确保我们的搜索查询返回一些结果。如果numPhotos == 0错误(“从Flickr中检索照片失败。XML响应是:%s'...xmlwrite(响应));结束否则,将搜索结果转换为结构单元格数组%,包含搜索结果信息。photoInfo = cell(1, numPhotos);idx = 1:numPhotos节点= photos.item(idx-1);photoInfo{idx} = struct(“农场”char (node.getAttribute (“农场”)),...“服务器”char (node.getAttribute (“服务器”)),...“id”char (node.getAttribute (“id”)),...“秘密”char (node.getAttribute (“秘密”)),...“主人”char (node.getAttribute (“主人”)));结束

定义一个函数来检索和处理照片

对于每个搜索结果,我们需要运行一个函数来检索图像数据。该函数还通过Flickr评论搜索来自astrometry.net的结构化信息,并返回望远镜指向的方向。在下一阶段中,我们将使用parfeval

函数[photo, location, username] = getAstrometryPhotoFromFlickr(appKey, info)首先,根据Flickr文档建立照片URL%这里:Url = sprintf(“http://farm%s.staticflickr.com/%s/%s_%s.jpg”...信息。农场,信息。服务器信息。id, info.secret);试一试图片= imread(url);E有时读失败。再试一次。图片= imread(url);结束获取照片信息以提取用户名Url = [“http://api.flickr.com/services/rest/”...”?方法= flickr.photos.getInfo '...“api_key = 'appKey,“&photo_id = 'info.id);Response = xmlread(url);owner = response.getDocumentElement.getElementsByTagName(“主人”);如果getLength(owner) == 1 username = char(owner.item(0).getAttribute(“用户名”));其他的用户名=“未知”结束接下来,查看要提取的照片的注释%来自astrometry.net的注释。Url = [“http://api.flickr.com/services/rest/”...”?方法= flickr.photos.comments.getList '...“api_key = 'appKey,“&photo_id = 'info.id);Response = xmlread(url);从XML响应中获取所有实际的注释元素。comments = response.getDocumentElement.getElementsByTagName(“评论”);遍历所有的评论,通过astrometry.net寻找第一个%,包含关于照片的信息。idx = 0:(getLength(comments)-1) comment = comments.item(idx);如果比较字符串(char (comment.getAttribute (“authorname”)),“astrometry.net”%我们已经找到评论,提取评论文本。commentText = char(comment.getTextContent());将位置信息提取到行向量中%使用正则表达式。locationText = regexprep(...commentText,”。*中心:* \(([0 - 9。\] +)) *度。*’“1美元”);location = sscanf(locationText,“% g”,, [1, 2]);返回结束结束我们没有找到astrometry.net的评论,所以位置未知。。location = [NaN, NaN];结束

使用parfeval向并行工作人员提交工作以读取图像

对于每个搜索结果,我们将创建一个parfeval请求特定的结果。这将导致我们的一个工人平行池调用该函数。如果并行池尚未打开,则将自动创建一个并行池。每一个parfeval调用返回一个平行的。未来实例。的parfeval请求由并行池工作人员按顺序执行。的语法parfeval与MATLAB函数相当相似函数宏指令,除了因为求值不会立即发生,所以必须指定希望请求多少输出参数。在本例中,我们希望从getAstrometryPhotoFromFlickr

idx = 1:numPhotos期货(idx) = parfeval(@getAstrometryPhotoFromFlickr, 3,...appKey, photoInfo {idx});结束
使用“本地”配置文件启动并行池(parpool)…与6名工人相连。

准备一个用于显示结果的图形

当工作人员忙于从Flickr检索图像时,我们可以设置一个图形来显示这些图像。

创建一个新图形,最初不可见。打架=数字(“位置”, [200,200,600,800],...“单位”“像素”“可见”“关闭”);使用FEX提交'tight_subplot'设置坐标轴% //www.tatmou.com/matlabcentral/fileexchange/27991-tight-subplot-nh--nw--gap--marg-h--marg-w-axesHandles = tight_subplot(4,3, [0.06, 0.01], [0.01, 0.06], 0.01);轴(axesHandles“关闭”);

使用fetchNext检索结果,然后显示它们

现在,我们进入一个循环,等待工作人员的结果。我们使用fetchNext为了达到这个目的。我们通过fetchNext我们的数组期货,当另一个元素完成并且有新的结果可用时,它返回。我们还可以指定等待每个新结果的最大时间,这样,如果web服务运行的时间非常长,我们可以优雅地中止执行。

请注意来自的结果fetchNext可以以任何顺序到达,并且我们使用第一个输出参数originalIdx算出的元素期货结果对应于。

我们将指定等待所有期货交易完成的时间的上限。如果我们超过了这个时间限制,还有期货在运行,我们可以取消它们。

overallTimeLimit = 10;%秒T = tic;集(figHandle,“可见”“上”);numCompleted = 0;numCompleted < numPhotos试一试%此阻塞最多1秒等待结果。[originalIdx,照片,位置,用户]= fetchNext(期货,1);E有时,URL根本无法读取,因此%错误由工作线程抛出。我们来显示一下%并继续下去。警告('读取映像失败:%s'getReport (E));originalIdx = [];结束如果'fetchNext'成功完成,则originalIdx . %%将非空,并将索引包含在“futures”中%对应于刚刚完成的工作。如果~ isempty (originalIdx)显示照片的归属和原始链接流('图片%2d由Flickr用户:%s\n', originalIdx, user);info = photoInfo{originalIdx};流(原文地址:http://www.flickr.com/%s/%s/\n,信息。主人,info.id);拣起我们的斧头:axesToUse = axesHandles(originalIdx);显示图像图像(照片,“父”, axesToUse);轴(axesToUse“关闭”);轴(axesToUse“平等”);将轴的标题设置为位置标题(axesToUse num2str(位置));numCompleted = numCompleted + 1;elseiftoc(t) > overallTimeLimit我们的时间已经超出预算了!disp (“时间限制已过!”);取消期货将停止任何运行的执行%期货,但对已经完成的期货没有影响。取消(期货);打破结束结束toc (t);
照片6 Flickr用户:s58y原始:http://www.flickr.com/45032885@N04/4145493112照片2 Flickr用户:davedehetre原始:http://www.flickr.com/22433418@N04/4950431138照片5 Flickr用户:s58y原始:http://www.flickr.com/45032885@N04/8541349810照片1通过Flickr用户:s58y原始:http://www.flickr.com/45032885@N04/4553112538照片4 Flickr用户:托本Bjørn汉森原始:http://www.flickr.com/21067003@N07/6105409913照片3 Flickr用户:哈利托马斯摄影最初从http://www.flickr.com/84598277@N08/8882356507图7通过Flickr用户:s58y原始:http://www.flickr.com/45032885@N04/4144380775照片8 Flickr用户:杨晨罗伯茨原始:http://www.flickr.com/8374715@N06/8719966332照片9 Flickr用户:s58y原始:http://www.flickr.com/45032885@N04/4145140448照片11 Flickr用户:davedehetre原始:http://www.flickr.com/22433418@N04/4954464378照片12 Flickr用户:s58y原始:http://www.flickr.com/45032885@N04/4535865643/ Photo 10 by Flickr user: cfaobam Original at: http://www.flickr.com/33763963@N05/7060054229/流逝的时间是2.897368秒。

结论

我们已经看到如何使用parfeval命令可用于从web服务检索数据,并在结果可用时交互式地显示结果。parfeval让你有更多的灵活性parfor:

  1. 在并行计算进行时绘制结果
  2. 优雅地跳出并行计算

如果您曾经想要显示一个等待条或绘制部分结果parfor循环,然后您可能能够调整您的代码来使用parfeval.如果你有任何进一步的想法,请告诉我们在这里




发布与MATLAB®R2013b

|
  • 打印
  • 发送电子邮件

评论

如欲留言,请点击在这里登录您的MathWorks帐户或创建一个新帐户。