小编ead*_*ead的帖子

将多个子模块折叠为一个Cython扩展

这个setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

extensions = (
    Extension('myext', ['myext/__init__.py',
                        'myext/algorithms/__init__.py',
                        'myext/algorithms/dumb.py',
                        'myext/algorithms/combine.py'])
)
setup(
    name='myext',
    ext_modules=cythonize(extensions)
)
Run Code Online (Sandbox Code Playgroud)

没有预期的效果.我想要它生产单一的myext.so,它做的; 但是当我通过它调用它时

python -m myext.so
Run Code Online (Sandbox Code Playgroud)

我明白了:

ValueError: Attempted relative import in non-package
Run Code Online (Sandbox Code Playgroud)

由于myext试图参考的事实.algorithms.

知道如何让这个工作吗?

python distutils python-module cython

10
推荐指数
3
解决办法
3255
查看次数

GDB:如何从自动显示中删除变量

我偶然发现了gdb的自动显示功能,这非常强大和方便.打电话后

(gdb) display/i $pc
(gdb) display $rax
Run Code Online (Sandbox Code Playgroud)

每个步骤后自动显示观察值:

(gdb) si
0x0804805e in print_loop_start ()
2: $rax = 0
1: x/i $pc
=> 0x804805e <print_loop_start+6>:  mov    0x4(%ebp,%eax,4),%ecx
Run Code Online (Sandbox Code Playgroud)

但是,如果不再感兴趣,我如何"取消"$ rax中的价值?

gdb

10
推荐指数
1
解决办法
8766
查看次数

对于复数乘法,g ++与手动优化

在我们的代码库中,我们有很多操作,如j*ω*X,其中j是虚数单位,ω是实数,X是复数.实际上很多循环看起来像:

#include <complex>
#include <vector>

void mult_jomega(std::vector<std::complex<double> > &vec, double omega){
    std::complex<double> jomega(0.0, omega);
    for (auto &x : vec){
        x*=jomega;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我们利用了真实部分jomega为零的事实并将乘法写为:

void mult_jomega_smart(cvector &vec, double omega){
    for (auto &x : vec){
        x={-omega*x.imag(), omega*x.real()};
    }
}
Run Code Online (Sandbox Code Playgroud)

一开始,我对这种"聪明"的转变不屑一顾,因为

  1. 它更难理解.
  2. 错误的概率更高.
  3. "无论如何,编译器都会优化它".

然而,正如一些表现回归所显示的那样,第三个论点并不成立.当比较这两种功能(见下文列表),智能版采用一贯优于-O2以及具有-O3:

size    orig(musec)   smart(musec)  speedup
10      0.039928      0.0117551     3.39665
100     0.328564      0.0861379     3.81439
500     1.62269       0.417475      3.8869
1000    3.33012       0.760515      4.37877
2000    6.46696       1.56048       4.14422
10000   32.2827       9.2361        3.49528
100000  326.828       115.158       2.8381 …
Run Code Online (Sandbox Code Playgroud)

c++ optimization gcc clang

9
推荐指数
1
解决办法
604
查看次数

了解std :: isnan的编译结果

我一直认为,测试NANvia 之间几乎没有区别

  • x!=x

要么

  • std::isnan(x)

但是,gcc为这两个版本提供了不同的汇编程序(在godbolt.org上直播):

  ;x!=x:
  ucomisd %xmm0, %xmm0
  movl $1, %edx
  setne %al
  cmovp %edx, %eax
  ret

  ;std::isnan(x)
  ucomisd %xmm0, %xmm0
  setp %al
  ret
Run Code Online (Sandbox Code Playgroud)

但是,我很难理解这两个版本.我天真的尝试编译std::isnan(x)将是:

  ucomisd %xmm0, %xmm0
  setne %al   ;return true when not equal
  ret
Run Code Online (Sandbox Code Playgroud)

但我必须遗漏一些东西.

可能在x!=x-version中缺少优化(编辑:它可能是gcc-8.1中回归).

是,是我的问题,为什么奇偶标志(setp,PF=1(),而不是平等的标志setne,ZF=0)用在第二个版本?

c++ optimization x86 gcc ieee-754

9
推荐指数
1
解决办法
107
查看次数

Linux和Windows上缓冲stdout的区别

stdout写入控制台时,在Windows和Linux上缓冲的方式似乎有所不同.考虑一下这个小python脚本:

import time
for i in xrange(10):
    time.sleep(1)
    print "Working" ,
Run Code Online (Sandbox Code Playgroud)

在Windows上运行此脚本时,我们看到Working一个接一个地出现在中间的第二个等待.在Linux上,我们必须等待10秒,然后立即出现整行.

如果我们将最后一行更改为print "Working",则每行都会单独出现在Linux上.

所以在Linux上,stdout似乎是行缓冲而在Windows上根本没有.我们可以使用-u-option 关闭缓冲(在这种情况下,Linux上的脚本具有与Windows上相同的行为).该文件说:

-u强制stdin,stdout和stderr完全无缓冲.

实际上,它并没有说,没有-u-option stdin并且stdout是缓冲的.因此我的问题是:

  1. 在Linux/Windows上出现不同行为的原因是什么?
  2. 是否有某种保证,如果重定向到文件,stdout将被缓冲,无论哪个操作系统?至少在Windows和Linux中就是这种情况.

信息被刷新时,我的主要关注点不是(正如一些答案所假设的),但如果stdout没有缓冲,则可能是严重的性能损失而且不应该依赖它.

编辑:值得注意的是,对于Python3,Linux和Windows的行为是相同的(但这并不奇怪,因为行为是由print-method 的参数显式配置的).

python linux windows stdout

8
推荐指数
1
解决办法
1231
查看次数

如何在Clojure中替换向量中的最后一个元素

作为Clojure的新手,我经常难以表达最简单的事情.例如,用于替换向量中的最后一个元素

v[-1]=new_value
Run Code Online (Sandbox Code Playgroud)

在python中,我最终得到了Clojure中的以下变体:

(assoc v (dec (count v)) new_value)
Run Code Online (Sandbox Code Playgroud)

至少可以说,这是非常漫长和无意义的,或者

(conj (vec (butlast v)) new_value) 
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,因为它有O(n)运行时间.

这让我觉得很傻,就像一个试图用俱乐部修理瑞士手表的穴居人.

用Clojure方法替换向量中的最后一个元素是什么?


为了支持我的O(n)-claim for butlast-version(Clojure 1.8):

(def v (vec (range 1e6)))
#'user/v
user=> (time (first (conj (vec (butlast v)) 55)))
"Elapsed time: 232.686159 msecs"
0
(def v (vec (range 1e7)))
#'user/v
user=> (time (first (conj (vec (butlast v)) 55)))
"Elapsed time: 2423.828127 msecs"
0
Run Code Online (Sandbox Code Playgroud)

所以基本上10次元素的数量要慢10倍.

clojure

8
推荐指数
1
解决办法
661
查看次数

移动返回对象的构造函数会破坏C ++ 98代码?

标准不需要编译器执行返回值优化(RVO),但是从C ++ 11开始,必须移动结果。

看来,这可能会将UB引入到/破坏代码中,这在C ++ 98中是有效的。

例如:

#include <vector>
#include <iostream>

typedef std::vector<int> Vec;
struct Manager{
    Vec& vec;
    Manager(Vec& vec_): vec(vec_){}
    ~Manager(){
        //vec[0]=42; for UB
        vec.at(0)=42;
    }
};

Vec create(){
    Vec a(1,21);
    Manager m(a);
    return a;
}

int main(){
    std::cout<<create().at(0)<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

当使用gcc(或与此相关的clang)进行编译时(为了简化示例,-O2 -fno-inline -fno-elide-constructors我正在使用std::vector这些build-option。如果没有这些选项以及手工类和更复杂的create功能,则可能会触发相同的行为)对于C ++ 98(-std=c++98)一切正常:

  1. return a;触发复制构造函数,它保持a原样。
  2. 的Destructor m称为(必须在a被销毁之前发生,因为它m是在之后构造的a)。a在析构函数中访问是没有问题的。
  3. 的析构a函数称为。

结果与预期的一样:21已打印(此处为live)。 …

c++ gcc rvo c++11

8
推荐指数
1
解决办法
328
查看次数

错误:“PyThreadState”{aka“struct _ts”}没有名为“exc_type”的成员;您的意思是“curexc_type”吗?构建 Cython 扩展时

我在 Python 3.8 中收到以下错误,而在 Python 3.6 中则没有收到该错误。我怎样才能让它与Python 3.8一起工作?为了重现该错误,请按照此处操作: https: //github.com/davidstutz/mesh-fusion/issues/7

\n
[3645:3637 0:2090] 11:04:08 Tue Jan 12 [mona@goku:pts/0 +1] ~/mesh-fusion/libfusiongpu\n$ python setup.py build_ext --inplace\nAdded OpenMP\nrunning build_ext\nskipping \'cyfusion.cpp\' Cython extension (up-to-date)\nbuilding \'cyfusion\' extension\nx86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/mona/venv/tsdf/lib/python3.8/site-packages/numpy/core/include -I/home/mona/venv/tsdf/include -I/usr/include/python3.8 -c cyfusion.cpp -o build/temp.linux-x86_64-3.8/cyfusion.o -ffast-math -msse -msse2 -msse3 -msse4.2 -fopenmp\nIn file included from /home/mona/venv/tsdf/lib/python3.8/site-packages/numpy/core/include/numpy/ndarraytypes.h:1822,\n                 from /home/mona/venv/tsdf/lib/python3.8/site-packages/numpy/core/include/numpy/ndarrayobject.h:12,\n                 from /home/mona/venv/tsdf/lib/python3.8/site-packages/numpy/core/include/numpy/arrayobject.h:4,\n                 from cyfusion.cpp:531:\n/home/mona/venv/tsdf/lib/python3.8/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning "Using …
Run Code Online (Sandbox Code Playgroud)

c++ python linux struct cython

8
推荐指数
1
解决办法
8716
查看次数

干净地压制gcc的'final`建议警告(`-Wsuggest-final-types`和`-Wsuggest-final-methods`)

我喜欢使用-Wsuggest-final-types-Wsuggest-final-methods编译我的代码,以便警告final关键字可用于允许编译器更积极地优化的机会.

但有时候,建议是不正确的 - 例如,我有一个Base带有virtual ~Base()析构函数的类,在另一个项目中以多态方式使用,gcc建议我Base可以标记为final.

有没有办法"干净地"告诉编译器Base多态使用并且不应该标记为final

我能想到的唯一方法是使用#pragma指令,但我发现它使代码混乱且难以阅读.

理想情况下,我正在寻找non-final可以在类/方法声明中添加/附加的关键字或属性.

c++ gcc warnings final

7
推荐指数
1
解决办法
531
查看次数

在x86-64中使用32位寄存器/指令的优点

有时gcc使用32位寄存器,当我希望它使用64位寄存器时.例如以下C代码:

unsigned long long 
div(unsigned long long a, unsigned long long b){
    return a/b;
}
Run Code Online (Sandbox Code Playgroud)

使用-O2选项编译(省略一些样板文件):

div:
    movq    %rdi, %rax
    xorl    %edx, %edx
    divq    %rsi
    ret
Run Code Online (Sandbox Code Playgroud)

对于无符号除法,寄存器%rdx需要0.这可以通过xorq %rdx, %rdxxorl %edx, %edx似乎具有相同的效果来实现.

至少在我的机器上没有性能提升(即加速)进行xorlxorq.

我实际上不只是一个问题:

  1. 为什么gcc更喜欢32位版本?
  2. 为什么gcc会停止xorl并且不使用xorw
  3. 有没有xorl比这更快的机器xorq
  4. 如果可能的话,总是更喜欢32位寄存器/操作而不是64位寄存器/操作吗?

assembly gcc x86-64 micro-optimization

7
推荐指数
2
解决办法
749
查看次数