记一次tensorflow debug过程

本周有个TF问题困扰一周,周末闲着无聊,debug一天,本着更加无聊的思路,写下本文。。。

起因

在用单机4卡跑TF模型时,遇到了如下错误:

38430 Aborted                 (core dumped) $@

一脸懵逼,之前看过TF的core文件,由于是多线程异步的,几十个线程又非常相似,如果不是对底层API非常了解,还是建议先别看了。。。

分布式环境到本地mac环境

由于线上的单机多卡环境是在集群上提交的,为了模拟线上环境,在mac本地搭建了本地计算图计算模型。 本地跑完了整个流程,完全没发现错误,只能得到一个结论:计算图本身并没有问题。

排除数据错误

既然计算图并没有问题,那么可能是数据异常造成的错误了。

本地数据检查

由于读取的数据是spark来生成tfrecord的,首先用spark统计各个数据指标,并未发现不符合要求的。接着在本地mac环境跑计算图,使用较小的valid数据集时并不能复现问题。而且将tfrecord的数据解析,也并未发现错误。

远程数据检查

小数据集上并不能复现该问题,然而在线上大数据集上仍然出现了该问题。考虑是大数据集上某些数据造成了问题,采用了人肉二分法。发现part-r-00210、part-r-00215等数据上能复现该问题。

本地分布式环境

考虑到可能是本地并没有复现分布式的环境,于是将本地mac也改成单机多卡方式,同时

allow_soft_placement = True

将有问题数据集下载到本地,终于完整复现了问题,同时得到了提示:

tensorflow/core/framework/tensor.cc:746] Check failed: 0 <= start (0 vs. -2147483648)

同时也发现个有趣的问题,不同的batch_size下,有时候能复现,有时候不能复现。。。

Tensorflow源码查看

根据提示查看git v1.4.0tensor.cc 746行代码如下:

Tensor Tensor::Slice(int64 start, int64 limit) const {
  CHECK_GE(dims(), 1);
  CHECK_LE(0, start);
  CHECK_LE(start, limit);
  int64 dim0_size = shape_.dim_size(0);
  CHECK_LE(limit, dim0_size);
  if ((start == 0) && (limit == dim0_size)) {
    return *this;
  Tensor ret;
  ret.shape_ = shape_;
  ret.set_dtype(dtype());
  ret.buf_ = nullptr;
  if (dim0_size > 0) {
    const int64 elems_per_dim0 = NumElements() / dim0_size;
    const int64 delta = start * elems_per_dim0;
    dim0_size = limit - start;
    ret.shape_.set_dim(0, dim0_size);
    const int64 num_elems = dim0_size * elems_per_dim0;
    if (buf_) {