Vecparser: 向量化任意层Matlab, CVX 的for循环的语法解析器

文章介绍了一种名为Vecparser的工具,它能将MATLAB和CVX中的for循环尽可能向量化,显著提高程序运行速度。作者分享了示例、性能测试结果以及项目注意事项,未来计划扩展功能并提及了许可证和引用要求。
摘要由CSDN通过智能技术生成


在这里插入图片描述

Vecparser 是一个自动将任意层 for 循环(在 MATLAB、CVX 中)尽可能向量化的解析器,由此节省大量的程序运行时间(有时高达97%)。这项技术基于我2022年发在 CVX论坛 的原创帖子。完整项目在github项目地址

快速启动

先克隆仓库

git clone https://github.com/jackfsuia/Vecparser.git

然后运行下面命令安装依赖项,

pip install sly

要向量化你的 MATLAB 和 CVX 中的 for 循环,请先将循环写到 loop_eiditor.m,在此之前建议读一下注意事项)。 然后运行

python vecparser.py

大功告成! 向量化后的表达式也会打印在 loop_eiditor.m , 所以请刷新一下这个文件。

示例

比如下面的原始循环,先把它抄到loop_eiditor.m如下:

% loop_eiditor.m
for n1=1:N1
    for n2=1:N2
        for n3=1:N3
            for n4=1:N4
                if n1~=n2*n3 && n3>n4^3
                    x(n1,n2,n3,n4)= (y(n1,n3)+z(n4))*h(n2,n3,n1); % 注意: size(z) 必须是 "N4 1", 而不是 "1 N4"。
                    q(n4,n3,n2,n1)= -h(n2,n3,n1)+((y(n1,n3)+z(n4))*h(n2,n3,n1))^2;
                end
            end
        end
    end
end

然后运行下面命令

python vecparser.py

结果就会附加到 loop_eiditor.m 后面,如下

% loop_eiditor.m
for n1=1:N1
    for n2=1:N2
        for n3=1:N3
            for n4=1:N4
                if n1~=n2*n3 && n3>n4^3
                    x(n1,n2,n3,n4)= (y(n1,n3)+z(n4))*h(n2,n3,n1); % 注意: size(z) 必须是 "N4 1", 而不是 "1 N4"。
                    q(n4,n3,n2,n1)= -h(n2,n3,n1)+((y(n1,n3)+z(n4))*h(n2,n3,n1))^2;
                end
            end
        end
    end
end

%-------------------------vectorized by Vecparser as-----------------------

cached_condition_for_this=(permute(repmat(repmat((1:N1)',1,N2,N3)~=permute(repmat(repmat((1:N2)',1,N3).*permute(repmat((1:N3)',1,N2),[2,1]),1,1,N1),[3,1,2]),1,1,1,N4),[2,3,1,4])&permute(repmat(permute(repmat((1:N3)',1,N4),[2,1])>repmat((1:N4)'.^3,1,N3),1,1,N2,N1),[3,2,4,1]));

x=permute(permute((cached_condition_for_this),[4,1,2,3]).*permute((permute(repmat((permute(repmat(y,1,1,N4),[1,3,2])+permute(repmat(z,1,N1,N3),[2,1,3])),1,1,1,N2),[4,3,1,2]).*repmat(h,1,1,1,N4)),[4,1,2,3])+permute((1-permute((cached_condition_for_this),[3,4,1,2])),[2,3,4,1]).*permute(x,[4,2,3,1]),[4,2,3,1]);

q=permute(permute((cached_condition_for_this),[4,1,2,3]).*permute((repmat(-h,1,1,1,N4)+permute(permute((permute(repmat((permute(repmat(y,1,1,N4),[1,3,2])+permute(repmat(z,1,N1,N3),[2,1,3])),1,1,1,N2),[4,3,1,2]).*repmat(h,1,1,1,N4)),[3,4,1,2]).^2,[3,4,1,2])),[4,1,2,3])+permute((1-permute((cached_condition_for_this),[3,4,1,2])),[2,3,4,1]).*permute(q,[1,3,2,4]),[1,3,2,4]);

%-----Please clear this file each time before you write a new loop on------

现在将结果复制到你的 matlab 中去替换原始的循环,试着运行一下。

觉得有用的话,请帮我们github项目点颗星 ⭐️ ,谢谢~~

性能表现

我在老电脑上跑了仿真,电脑配置是: Intel® Xeon® CPU E5-2660 v2 @ 2.20GHz, RAM 16G. 结果如下:
在这里插入图片描述

另外,当迭代次数过大的时候,向量化for循环会因为内存不足而导致电脑死机吗,在这些情况下向量化跑的反而没有原始循环那么快。或许内存不足的时候得在向量化和for循环之间做权衡,或许当考虑用GPU来计算的时候整个情况又会更微妙。

注意事项

支持任意位置的多个嵌套if块和非if块, 支持所有Matlab向量化运算符,支持自定义的输出输入维度不变的向量化函数,支持CVX的凸不等式、等式:>=,<=,==。 这是个实验性的项目,现阶段可能有一些bug。欢迎反馈。

未来工作

  • 支持降维式运算符,比如 sum, norm, *(矩阵乘)。
  • 推广到其他语言 (e.g., python)。

许可证

Vecparser 根据位于此仓库根目录中的 LICENSE 文件中的 Apache 2.0 许可证授权。

引用

如果这项工作对你有所帮助,请引用为:

@article{Vecparser,
  title={Vecparser: a parser that vectorizes your nested for-loops (in MATLAB, CVX) as much as possible.}, 
  author={Yannan Luo},
  year={2024},
  url={https://github.com/jackfsuia/Vecparser}
}

致谢

这个仓库使用了pymatlabparser 中的 matlablexer。此仓库的pymatlabparser文件夹完全是从那里复制过来的,几乎没有修改。感谢他们出色的工作。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值