oneflow
oneflow copied to clipboard
OneFlow is a deep learning framework designed to be user-friendly, scalable and efficient.
重构 uniform 相关的 initializer,使用 oneflow 自己的 kernel,加速初始化
fix #9390 使 tensor.retain_grad 和 autograd.grad 解耦,同时重新考虑 GraphTask 内的数据结构,减小查表次数
Add cdist op
cdist 对于两个输入 x1 (shape=[B, R1, C]),x2 (shape=[B, R2, C]),计算每个 batch 内 x1 和 x2 每一行向量之间距离的p范数,得到结果 result (shape=[B, R1, R2])。 torch 文档见 https://pytorch.org/docs/stable/generated/torch.cdist.html
优化scalar_tensor.item的性能,使其耗时从pytorch的2-3倍降到pytorch的70%-80%。 ## 优化手段 ### 优化scalar_tensor.item的python层代码 原本的scalar_tensor.item是用python代码实现的:`scalar_tensor.cpu().numpy()[0]`。不论是tensor.cpu,tensor.numpy还是numpy.__getitem__,对于scalar_tensor.item都过于重度,因为scalar_tensor.item整个过程描述起来非常简单:从tensor内存中获取一个标量。显然,用一个专用的c++ api来加速这个过程是很合适的。 ### 优化scalar_tensor.item的main线程c++代码 旧版scalar_tensor.item的c++代码最终会调用AccessBlobByCallback指令。该指令构建的成本大概4-7个us,主要是一系列对象的创建成本,但其实这个构建成本可以通过复用指令对象减少到纳秒级。 上述所说的复用指令对象并不是直接复用AccessBlobByCallback指令,而是复用新设计的SyncRead指令。可以复用的根本原因是当前线程同一时间只会提交一条SyncRead指令给vm(因为是同步,main线程处理下一次SyncRead的时候,上一次SyncRead一定已经执行完)。SyncRead指令复用的方式可以采用简单的thread_local变量,确保main线程从python进入c++到最终提交指令到vm之间,不会有任何堆对象的创建。 ### 加速SyncRead的执行 SyncRead与AccessBlobByCallback的基本逻辑大致相同,但是由于前者专用于小数据的拷贝,我们可以用临时的pined_memory做cudaAsyncMemcpy。这种方式相比于AccessBlobByCallback所用的pageable memory,能缩短cudaAsyncMemcpy操作大概5us的时间,因为省去了同步操作。 ### 加速main线程的唤醒 旧版AccessBlobByCallback使用BlockingThenBusy来让worker线程唤醒main线程,具体做法是在cudaAsyncMemcpy之前通过BlockingThenBusy.blocking_cnt唤醒main线程,让main线程进入对BlockingThenBusy.spin_cnt的忙等,cudaAsyncMemcpy之后再对BlockingThenBusy.spin_cnt减一,让main线程执行BlockingThenBusy.spin_cnt之后的代码。这么做是为了用blocking wait减少cpu的空耗,而用busy wait加速main线程的响应。 上述过程中,worker线程调用posix接口pthread_cond_broadcast唤醒main线程。但是这个pthread_cond_broadcast也是有时间开销的,大概在1us-4us。这个开销同样可以想办法去掉,具体方法是main线程如果发觉vm上指令非常少(比如少于3条),它可以相信这些指令会在很快执行完,所以main线程可以选择不做blocking wait。这样main线程就不会进入睡眠,而worker线程也就不用花1us-4us来执行pthread_cond_broadcast。值得一提的是,原本的BlockingThenBusy不能帮助worker线程跳过pthread_cond_broadcast,本pr重构了BlockingThenBusy的内部实现以达成这一目的。 ### 加速worker线程的响应 旧版worker线程的工作模式是blocking wait方式等待指令,执行完指令后进入下次迭代的blocking wait。这种方式下,指令从scheduler线程到worker线程的切换开销大概在2-7us的样子,这对流水很弱的eager代码非常不利。 我们可以尝试让worker线程不要那么着急睡眠的方式工作,让它在每次执行完一条执行之后在线(使用std::this_thread::yield)等待大概200us,这段时间足够让main线程把后续的eager op准备好,穿过scheduler线程,worker线程在线接到任务就立刻开始干,这样就能省去线程切换的2-7us。
## Summary ``` AttributeError: module 'oneflow' has no attribute 'quantile' ``` ## Code to reproduce bug Please post a minimal example to repro the bug. GitHub Gist or repo is...
修复flow.logsumexp 计算结果上溢的错误: ```python >>> import oneflow as flow >>> x = flow.tensor([100, 200]) >>> flow.logsumexp(x, 0) /home/hanbinbin/oneflow/python/oneflow/framework/tensor_str.py:145: RuntimeWarning: invalid value encountered in true_divide nonzero_finite_max / nonzero_finite_min > 1000.0 tensor(inf, dtype=oneflow.float32)...
Add stft op
一. 涉及到` fft `运算部分 - cpu kernel 底层` fft `运算采用`pocketfft_hdronly.h` 库(外部引入库文件) - cuda kernel 底层 `fft `运算采用 cuda 自带的`cufft`库 (只支持cuda 11.0以上版本) - 针对fft运算封装好对应的类,后续根据需要可进行扩展 二. `stft `算子相关工作 - 未支持参数:return_complex