如何提高内联功能效率?

时间:2015-05-04 03:13:48

标签: c++ performance optimization inline

我描述了我的代码并发现一个内联函数占用了大约8%的样本。该函数用于将矩阵下标转换为索引。它非常类似于matlab函数sub2ind

inline int sub2ind(const int sub_height, const int sub_width, const int width) {
    return sub_height * width + sub_width;
}

我猜编译器不执行内联扩展,但我不知道如何检查它。

有没有办法改善这个?或者明确让编译器执行内联扩展?

2 个答案:

答案 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

因此,如果您确信您的函数没有内联,请首先确保在编译器选项中启用优化。

相关问题