2016-10-21 86 views
0

我是C++的新手,但设法为tensorflow创建了一个原始的新CPU。现在我想制定一个GPU的操作。我有一些开放式工作经验。我在这里以下指南:下面编译自定义tensorflow GPU时遇到的问题

https://www.tensorflow.org/versions/r0.11/how_tos/adding_an_op/index.html#gpu-support

是我的C++代码,其次是CUDA文件。我对这段代码不做任何事情。它编译正确,但每次我尝试运行它,我得到一个核心转储。为了调试的目的,我已经删除了我的课程的所有内容,以便我可以专注于这个问题。这也基本上是这样说:

*** Error in `/usr/bin/python': free(): invalid next size (fast): 0x00007fef04033ba0 *** 

这里是d_grid_gpu.cc文件:

#include "tensorflow/core/framework/op.h" 
    #include "tensorflow/core/framework/op_kernel.h" 

    REGISTER_OP("DGridGpu") 
     .Input("grid: int32") 
     .Attr("start_x: int = 0") 
     .Attr("start_y: int = 0") 
     .Attr("stop_x: int = 28") 
     .Attr("stop_y: int = 28") 
     .Attr("size_x: int = 28") 
     .Attr("size_y: int = 28") 
     .Attr("wall_height: float = 2.5") 
     .Output("prev: int32"); 

    using namespace tensorflow; 

    void run(); 

    class DGridGpuOp : public OpKernel { 
     public: 
     explicit DGridGpuOp(OpKernelConstruction* context) : OpKernel(context) { 

     } 

     void Compute(OpKernelContext* context) override { 
     run(); 
     } 

    }; 

    REGISTER_KERNEL_BUILDER(Name("DGridGpu").Device(DEVICE_GPU), DGridGpuOp); 

这里是d_grid_gpu.cu.cc文件:

#if GOOGLE_CUDA 
    #define EIGEN_USE_GPU 
    #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" 


    // content here 

#include <stdio.h> 
#define SIZE 1024 

__global__ void VectorAdd(int *a, int *b, int *c, int n) 
{ 
    int i = threadIdx.x; 

    if (i < n) 
     c[i] = a[i] + b[i]; 
} 


    void run() { 
    int *a, *b, *c; 
    int *d_a, *d_b, *d_c; 

    a = (int *)malloc(SIZE*sizeof(int)); 
    b = (int *)malloc(SIZE*sizeof(int)); 
    c = (int *)malloc(SIZE*sizeof(int)); 

    cudaMalloc(&d_a, SIZE*sizeof(int)); 
    cudaMalloc(&d_b, SIZE*sizeof(int)); 
    cudaMalloc(&d_c, SIZE*sizeof(int)); 

    for(int i = 0; i < SIZE; ++i) 
    { 
     a[i] = i; 
     b[i] = i; 
     c[i] = 0; 
    } 

    cudaMemcpy(d_a, a, SIZE*sizeof(int), cudaMemcpyHostToDevice); 
    cudaMemcpy(d_b, b, SIZE*sizeof(int), cudaMemcpyHostToDevice); 
    cudaMemcpy(d_c, c, SIZE*sizeof(int), cudaMemcpyHostToDevice); 

    // blocks, threads 
    VectorAdd<<< 1, SIZE >>>(d_a, d_b, d_c, SIZE); 

    cudaMemcpy(c, d_c, SIZE*sizeof(int), cudaMemcpyDeviceToHost); 

    for(int i = 0; i < 10; ++i) 
     printf("output : c[%d] = %d\n", i, c[i]); 

    free(a); 
    free(b); 
    free(c); 

    cudaFree(d_a); 
    cudaFree(d_b); 
    cudaFree(d_c); 
} 

    #endif 

这里是我的代码用于构建op:

TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())') 

    nvcc -std=c++11 -c -o d_grid_gpu.cu.o d_grid_gpu.cu.cc \ 
    -I $TF_INC -D GOOGLE_CUDA=1 -x cu -Xcompiler -fPIC --expt-relaxed-constexpr 

    g++ -std=c++11 -shared -o d_grid_gpu.so d_grid_gpu.cc \ 
    d_grid_gpu.cu.o -I $TF_INC -fPIC -lcudart -D_GLIBCXX_USE_CXX11_ABI=0 -L /usr/lib/x86_64-linux-gnu/ 

这就是我的全部。正如我所说,cuda代码什么都不做,但整个op编译。我有python代码调用这个库,我没有包括在内。我相信我的cuda正在工作。我使用Ubuntu 16.10和CUDA 8

编辑 - 一些错误的转储之前:

*** Error in `/usr/bin/python': free(): invalid next size (fast): 0x00007f34f4033ba0 *** 
    ======= Backtrace: ========= 
    /lib/x86_64-linux-gnu/libc.so.6(+0x790cb)[0x7f35664f20cb] 
    /lib/x86_64-linux-gnu/libc.so.6(+0x8275a)[0x7f35664fb75a] 
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7f35664ff18c] 
    /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so(+0x22223a1)[0x7f354d7953a1] 
    /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so(+0x222b6a2)[0x7f354d79e6a2] 
    /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so(+0x221fd90)[0x7f354d792d90] 
    /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so(_ZN5Eigen26NonBlockingThreadPoolTemplIN10tensorflow6thread16EigenEnvironmentEE10WorkerLoopEi+0x3c8)[0x7f354d9f4ce8] 
    /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so(_ZNSt17_Function_handlerIFvvEZN10tensorflow6thread16EigenEnvironment12CreateThreadESt8functionIS0_EEUlvE_E9_M_invokeERKSt9_Any_data+0x22)[0x7f354d9f44b2] 
    /usr/lib/x86_64-linux-gnu/libstdc++.so.6(+0xbb8f0)[0x7f354b0408f0] 
    /lib/x86_64-linux-gnu/libpthread.so.0(+0x770a)[0x7f356684770a] 
    /lib/x86_64-linux-gnu/libc.so.6(clone+0x5f)[0x7f35665810af] 
    ======= Memory map: ======== 
    200000000-200100000 rw-s 3cf997000 00:06 570        /dev/nvidiactl 
    ... more memory map here... 

我希望这是有帮助的。我尝试了这一点,并有一段时间,我认为它工作,但我不能重现结果。

编辑:我已经改变了我的代码,但仍然得到了内存转储。

d_grid_gpu.cc

#include "tensorflow/core/framework/op.h" 
    #include "tensorflow/core/framework/op_kernel.h" 

    REGISTER_OP("DGridGpu") 
     .Input("grid: int32") 
     .Output("prev: int32"); 

    using namespace tensorflow; 

     void run(const int * in, int * out); 

    class DGridGpuOp : public OpKernel { 
     public: 
     explicit DGridGpuOp(OpKernelConstruction* context) : OpKernel(context) { 


     } 

     void Compute(OpKernelContext* context) override { 


     Tensor* prev_h = NULL; 

     const Tensor& grid_h = context->input(0); 

     auto grid = grid_h.flat<int32>();  

     OP_REQUIRES_OK(context, context->allocate_output(
            0, 
            TensorShape({64}), &prev_h)); 

     auto prev = prev_h->flat<int32>(); 

     run(grid.data(), prev.data()); // do something to grid_host and move it to prev_host 

     //exit 
     } 

    }; 

    REGISTER_KERNEL_BUILDER(Name("DGridGpu").Device(DEVICE_GPU), DGridGpuOp); 
    //REGISTER_KERNEL_BUILDER(Name("DGridGpu").Device(DEVICE_CPU), DGridGpuOp); 

d_grid_gpu.cu.cc

#if GOOGLE_CUDA 
    #define EIGEN_USE_GPU 
    #include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor" 

    #include <stdio.h> 
    #define SIZE 20 

     __global__ void VectorAdd(const int *in, int *out, int n) 
     { 
      int i = threadIdx.x; 

      if (i < n) 
       out[i] = in[i] + out[i]; 
     } 


     void run(const int * in, int * out) { 

      VectorAdd<<< 1, SIZE >>>( in, out, SIZE); 

     } 

    #endif 
+0

你可以把完整的错误跟踪?你也没有定义任何gpu代码。 – fabrizioM

+0

我修改了一些问题。 –

回答

0

简单来说,更大的问题是你正尝试将自己管理内存,但Tensorflow已经知道如何为你做这个。您应该使用Tensorflow的管理内存的机制;您不需要任何mallocfree,cudaMalloc,cudaFree,cudaMemcpy代码。

我会通过修改从教程中的GPU内核启动:

https://github.com/tensorflow/tensorflow/blob/r0.11/tensorflow/g3doc/how_tos/adding_an_op/cuda_op_kernel.cc https://github.com/tensorflow/tensorflow/blob/r0.11/tensorflow/g3doc/how_tos/adding_an_op/cuda_op_kernel.cu.cc

内核接收作为在GPU内存已分配的输入缓冲区。你只需要将他们的地址传递给GPU内核。

要为输出分配缓冲区,应该使用OpKernelContext::allocate_output()来分配张量并将其地址传递给GPU内核。还有一个allocate_temp()用于分配临时缓冲区。上面的例子以这种方式分配它的输出。默认情况下,在GPU上,这将在GPU内存中分配一个缓冲区。所以不需要自己分配内存或者将设备复制到主机。

您当前正在主机上填充缓冲区作为输入到内核,然后手动将其复制到GPU。使用GPU填充缓冲区或使用单独的Tensorflow运算符创建输入可能是最简单的;在需要时,Tensorflow负责主机 - >设备副本。

我希望这有助于!

+0

我相信你是对的,但我无法让自己工作。我修改了一下我的问题。你可以看看新的代码吗? –

0

如果我改变d_grid_gpu.cc如下,我可以得到 '的run()' 方法没有内存转储工作。最重要的是'REGISTER_KERNEL_BUILDER'行中的更改。现在它包含'DEVICE_CPU'规范而不是'DEVICE_GPU'。不知何故,虽然我觉得这不是张量开发公司会这样做的方式。

#include "tensorflow/core/framework/op.h" 
    #include "tensorflow/core/framework/op_kernel.h" 

    REGISTER_OP("DGridGpu") 
     .Input("grid: int32") 
     .Attr("start_x: int = 0") 
     .Attr("start_y: int = 0") 
     .Attr("stop_x: int = 28") 
     .Attr("stop_y: int = 28") 
     .Attr("size_x: int = 28") 
     .Attr("size_y: int = 28") 
     .Attr("wall_height: float = 2.5") 
     .Output("prev: int32"); 

    using namespace tensorflow; 

     void run(); 

    class DGridGpuOp : public OpKernel { 
     public: 
     explicit DGridGpuOp(OpKernelConstruction* context) : OpKernel(context) { 


     } 

     void Compute(OpKernelContext* context) override { 

     Tensor grid; 
     Tensor * prev; 

     grid = context->input(0); 
     auto grid_host = grid.template flat<int32>(); 

     OP_REQUIRES_OK(context, context->allocate_output(
            0, 
            TensorShape({64}), &prev)); 
     auto prev_host = prev->flat<int32>(); 

     run(); // do something to grid_host and move it to grid_prev 

     //exit 
     } 

    }; 

    REGISTER_KERNEL_BUILDER(Name("DGridGpu").Device(DEVICE_CPU), DGridGpuOp);