我描述了我的代码并发现一个内联函数占用了大约8%的样本。该函数用于将矩阵下标转换为索引。它非常类似于matlab函数sub2ind
。
inline int sub2ind(const int sub_height, const int sub_width, const int width) {
return sub_height * width + sub_width;
}
我猜编译器不执行内联扩展,但我不知道如何检查它。
有没有办法改善这个?或者明确让编译器执行内联扩展?
答案 0 :(得分:5)
您还记得使用优化进行编译吗?有些编译器有一个强制内联的属性,即使编译器不想:见this question。
但它可能已经存在;您可以尝试让编译器输出汇编代码并尝试检查确定的方式。
指数计算可能占您时间的很大一部分并不是不可信的 - 例如如果你的算法是从矩阵,一点点计算中读取,然后回写,那么索引计算确实是你计算时间的重要部分。
或者,你编写的代码编译器无法证明width
在整个循环中保持不变*,因此每次都必须从内存重新读取它,以确保。尝试将width
复制到本地变量并在内部循环中使用它。
现在,您已经说过这需要8%的时间 - 这意味着您不太可能可能获得比运行时间提高8%的任何东西,并且可能更多减。如果那个真的值得,那么要做的就是从根本上改变你遍历数组的方式。
e.g。
width
是编译时常量,则可以明确地将其设置为,例如作为模板参数,您的编译器可能能够使用乘法*:您可能已经做了一些愚蠢的事情,比如将矩阵的数据结构放在存储矩阵条目的内存中!因此,当您更新矩阵时,您可能会更改宽度。编译器必须防范这些漏洞,因此它无法进行优化,它显然应该能够做到。有时,在一个环境中的漏洞很可能是程序员在另一个环境中的明显意图。一般来说,这些类型的循环漏洞往往遍布整个地方,编译器更容易找到这些漏洞而不是人类注意到它们。
答案 1 :(得分:1)
如@ user3528438所述,您可以查看程序集输出。请考虑以下示例:
public function view_emp_dtr($a, $b)
{
$q = $this->db->query('SELECT tbl_tmpdtr.id, tbl_tmpdtr.userid, date(tbl_tmpdtr.in_out) as in_out, tbl_tmpdtr.status, tbl_employee.emp_id, tbl_employee.emp_lname, tbl_employee.emp_mname, tbl_employee.emp_fname, tbl_employee.emp_gender, tbl_employee.civil_status, tbl_employee.dob, tbl_employee.street, tbl_employee.barangay, tbl_employee.city, tbl_employee.province, tbl_employee.emp_contact, tbl_employee.spouse_lname, tbl_employee.spouse_mname, tbl_employee.spouse_fname, tbl_employee.spouse_gender, tbl_employee.relationship, tbl_employee.address, tbl_employee.spouse_num, tbl_employee.jobtitle_id, tbl_employee.store_id, tbl_employee.username, tbl_employee.password, tbl_employee.hiredate, tbl_employee.emp_status, tbl_employee.Image FROM tbl_tmpdtr INNER JOIN tbl_employee ON tbl_tmpdtr.userid = tbl_employee.emp_id WHERE in_out<='$a' AND in_out>='$b' GROUP BY tbl_tmpdtr.userid');
if($q->num_rows() > 0)
{
foreach($q->result() as $row)
{
$data[]= $row;
}
return $data;
}
}
在没有优化((defn get-client-ip [req]
(if-let [ips (get-in req [:headers "x-forwarded-for"])]
(-> ips (clojure.string/split #",") first)
(:remote-addr req)))
)的情况下进行编译会导致以下代码inline int sub2ind(const int sub_height, const int sub_width, const int width) {
return sub_height * width + sub_width;
}
int main() {
volatile int n[] = {1, 2, 3};
return sub2ind(n[0], n[1], n[2]);
}
没有内联:
g++ -S test.cc
在使用优化(sub2ind
)进行编译时会导致main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl $1, -16(%rbp)
movl $2, -12(%rbp)
movl $3, -8(%rbp)
movq -16(%rbp), %rax
movq %rax, -32(%rbp)
movl -8(%rbp), %eax
movl %eax, -24(%rbp)
movl -24(%rbp), %edx
movl -28(%rbp), %ecx
movl -32(%rbp), %eax
movl %ecx, %esi
movl %eax, %edi
call _Z7sub2indiii ; call to sub2ind
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
内联并且大部分已经过优化:
g++ -S -O3 test.cc
因此,如果您确信您的函数没有内联,请首先确保在编译器选项中启用优化。