Julia使用@turbo宏计算拉普拉斯算子出现MM类型索引错误如何解决
错误触发原因
这个报错是LoopVectorization.jl的@turbo宏做循环向量化时生成的向量化索引(即报错信息里的MM类型批量索引),和运行时动态计算的循环边界(2+a、N+5-a这类带变量的表达式)不兼容导致的。@turbo默认会把循环迭代变量转换为批量向量化索引,当循环上下界不是编译期常量时,就容易出现索引类型不匹配的问题。
解决方案
以下方案按优先级从高到低排序:
- 方法1:将固定参数
a改为编译期常量传递
实际使用中幽灵点数量a一般是固定值(你示例中就是固定的1),可以通过Val类型把a转为编译期可知的参数,让@turbo在编译阶段就能确定循环边界,规避动态索引问题。修改后的代码示例:
@inline @views function ∇²!(∇²u, u, N, h, ::Val{a}) where a inv_h² = 1/(h*h) @turbo for j = 2+a:N+5-a for i = 2+a:N+5-a ∇²u[i,j] = (u[i-1,j] + u[i+1,j] + u[i,j-1] + u[i,j+1] - 4*u[i,j]) * inv_h² end end return nothing end
调用函数时把原本传a的位置改成传Val(a)即可,比如∇²!(∇²u, u, N, h, Val(1))。
注:这里额外把h^2的计算移到了循环外,用乘法代替除法,属于通用的性能优化点,不影响逻辑
- 方法2:调整
@turbo参数兼容动态边界
如果你确实需要动态调整a的取值,可以给@turbo加上unsafe=true参数跳过边界检查,或者直接用兼容性更好的线程版宏@tturbo替换@turbo:
@turbo unsafe=true for j = 2+a:N+5-a for i = 2+a:N+5-a ∇²u[i,j] = (u[i-1,j] + u[i+1,j] + u[i,j-1] + u[i,j+1] - 4*u[i,j])/h^2 end end
注意:开启unsafe=true后需要你自行保证循环索引不会越界,不会触发Julia的默认边界检查
内容的提问来源于stack exchange,提问作者crevell
相关产品推荐
相关产品推荐

