我正在尝试通过改善空间局部性来重新排列循环顺序,从而改善矩阵乘法的运行时间。我有一个在c ++中的类中执行此操作的示例,但是尝试在Chapel中实现它导致了此错误。
var grid : [1..size, 1..size] uint(8);
var grid2 : [1..size, 1..size] uint(8);
var grid3 : [1..size, 1..size] int;
var grid4 : [1..size, 1..size] uint(8);
forall i in 1..size do
forall k in 1..size do
grid4 = grid[i,k];
forall j in 1..size do
grid3[i,j] += grid4 * grid2[k,j];
hello.chpl:20: error: 'i' undeclared (first use this function)
hello.chpl:20: error: 'k' undeclared (first use this function)
答案 0 :(得分:2)
有两种因素共同导致了这些错误:
1)教堂不是对空格敏感的语言。因此,在Python中,语句的缩进表示它们之间的关系,而Chapel并非如此。从这方面来说,它更像是C,C ++或Java。
2)循环语句中的do
关键字(或条件语句中的then
关键字)是一种速写形式,专用于其主体只有一个语句的控制结构。要在主体中创建带有多个语句的循环或条件语句,应使用大括号指定复合语句。编写Chapel程序的一种防御方法是始终使用大括号。请注意,合法时,我经常在幻灯片或StackOverflow帖子中使用速记,只是因为它更简洁。
结果,正确缩进的书面循环结构如下:
forall i in 1..size do
forall k in 1..size do
grid4 = grid[i,k];
forall j in 1..size do
grid3[i,j] += grid4 * grid2[k,j];
这说明了为什么在最终循环中无法访问i
和k
的原因-它们特定于先前的作用域。一种解决方法是:
forall i in 1..size do
forall k in 1..size {
grid4 = grid[i,k];
forall j in 1..size do
grid3[i,j] += grid4 * grid2[k,j];
}
或者,在完全括号中的版本中:
forall i in 1..size {
forall k in 1..size {
grid4 = grid[i,k];
forall j in 1..size {
grid3[i,j] += grid4 * grid2[k,j];
}
}
}
理想情况下,好的Chapel编辑器模式可以帮助您避免此类问题,但是目前,只有少数几种这样的编辑器模式可用,并且它们的质量各不相同。在Chapel安装中,您将在$CHPL_HOME/highlight
中找到emacs和vim模式(其中emacs模式往往不如vim模式成熟)。我相信在线上(可能还有其他)也可以使用原子模式,但是个人并不熟悉它们。
但是,正如我所说的,一种非常安全的编程方法是始终将花括号与控制流一起使用,在这种情况下,由于花括号不平衡,简单的错误通常会显示为语法错误。