2017-06-07 3 views
2

Ich versuche, TensorFlow lose ein neues Op nach this Dokument hinzuzufügen. Der Unterschied ist, dass ich versuche, einen GPU-basierten Op zu implementieren. Die Op, die ich hinzufügen möchte, ist die cuda op von here (cuda_op.py, cuda_op_kernel.cc, cuda_op_kernel.cu.cc). . Ich versuche, diese außerhalb von tensorflow zu kompilieren und die Verwendung tf.load_op_library sie in ziehen, habe ich einige Änderungen vorgenommen hier so sind meine Dateien:Hinzufügen einer GPU Op in Tensorflow

cuda_op_kernel.cc

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

using namespace tensorflow; // NOLINT(build/namespaces) 

REGISTER_OP("AddOne") 
    .Input("input: int32") 
    .Output("output: int32") 
    .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) { 
     c->set_output(0, c->input(0)); 
     return Status::OK(); 
    }); 

void AddOneKernelLauncher(const int* in, const int N, int* out); 

class AddOneOp : public OpKernel { 
public: 
    explicit AddOneOp(OpKernelConstruction* context) : OpKernel(context) {} 

    void Compute(OpKernelContext* context) override { 
    // Grab the input tensor 
    const Tensor& input_tensor = context->input(0); 
    auto input = input_tensor.flat<int32>(); 

    // Create an output tensor 
    Tensor* output_tensor = NULL; 
    OP_REQUIRES_OK(context, context->allocate_output(0, input_tensor.shape(), 
                &output_tensor)); 
    auto output = output_tensor->template flat<int32>(); 

    // Set all but the first element of the output tensor to 0. 
    const int N = input.size(); 
    // Call the cuda kernel launcher 
    AddOneKernelLauncher(input.data(), N, output.data()); 

    } 
}; 

REGISTER_KERNEL_BUILDER(Name("AddOne").Device(DEVICE_GPU), AddOneOp); 

cuda_op_kernel.cu

#define EIGEN_USE_GPU 
#include <cuda.h> 
#include <stdio.h> 

__global__ void AddOneKernel(const int* in, const int N, int* out) { 
    for (int i = blockIdx.x * blockDim.x + threadIdx.x; i < N; 
     i += blockDim.x * gridDim.x) { 
    out[i] = in[i] + 1; 
    } 
} 

void AddOneKernelLauncher(const int* in, const int N, int* out) { 
    AddOneKernel<<<32, 256>>>(in, N, out); 

    cudaError_t cudaerr = cudaDeviceSynchronize(); 
    if (cudaerr != cudaSuccess) 
    printf("kernel launch failed with error \"%s\".\n", cudaGetErrorString(cudaerr)); 
} 

CMakeLists.txt

cmake_minimum_required(VERSION 3.5) 

#found from running python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())' 
include_directories(/usr/local/lib/python3.5/dist-packages/tensorflow/include) 

find_package(CUDA) 

#set flags based on tutorial 
set (CMAKE_CXX_FLAGS "--std=c++11 -fPIC -O2 -D_GLIBCXX_USE_CXX11_ABI=0") 

#pass flags to c++ compiler 
SET(CUDA_PROPAGATE_HOST_FLAGS ON) 

#create library 
cuda_add_library(
    cuda_op SHARED 
    src/cuda_op_kernel.cu 
    src/cuda_op_kernel.cc 
    OPTIONS -gencode=arch=compute_20,code=sm_20) 

#copy test file to build folder 
configure_file(src/test.py test.py COPYONLY) 

test.py

import tensorflow as tf 
mod = tf.load_op_library('./libcuda_op.so') 
with tf.Session() as sess: 
    start = [5,4,3,2,1] 
    print(start) 
    print(mod.add_one(start).eval()) 

Ich bin in der Lage test.py erfolgreich zu kompilieren und ausführen, aber der Ausgang ist immer [0 0 0 0 0]. Wenn ich AddOneKernel<<<32, 256>>>(in, N, out); durch for (int i = 0; i < N; i++) out[i] = in[i] + 1; und DEVICE_GPU durch DEVICE_CPU ersetze, gibt das op die richtigen Werte aus [6 5 4 3 2] (mit genau demselben CMakeList.txt).

Haben Sie eine Idee, wie Sie die richtigen Werte erhalten?

Antwort

2

Ich kann mich nicht mehr genau erinnern, wo ich das Cmake-Zeug für CUDA gefunden habe, aber die Optionen haben die Zusammenstellung irgendwie durcheinander gebracht. Ersetzen Sie cuda_add_library in der CMakeLists.txt um das Problem zu beheben.

#no options needed 
cuda_add_library(
    cuda_op SHARED 
    src/cuda_op_kernel.cu 
    src/cuda_op_kernel.cc) 
0

ubuntu @ cubuntu: ~/Desktop/src/src/build $ cmake ..

- Gene

getan - - Build-Dateien wurden

getan Konfigurieren geschrieben:/home/ubuntu/Desktop/src/src/

ubuntu @ cubuntu bauen: ~/Desktop/src/src/build $ machen

[33%] Gebäude NVCC (Device) Objekt CMakeFiles/cuda_op.d/cuda_op_generated_cuda_op_kernel.cu.o

NVCC Warnung: Die 'compute_20', 'sm_20' und 'sm_21' Architekturen sind veraltet, und können in einer zukünftigen Version entfernt (Verwenden Sie -wo-deprecated-gpu-targets, um die Warnung zu unterdrücken).

Warnung nvcc: Die Architekturen 'compute_20', 'sm_20' und 'sm_21' sind veraltet und werden möglicherweise in einer zukünftigen Version entfernt (Verwenden Sie -wo-deprecated-gpu-targets, um Warnungen zu unterdrücken).

Scanning Abhängigkeiten von Ziel cuda_op

[66%] Gebäude CXX Objekt CMakeFiles/cuda_op.dir/cuda_op_kernel.cc.o /home/ubuntu/Desktop/src/src/cuda_op_kernel.cc: 1: 17: error: 'tensorflow' ist kein Namespace-Name mit Namespace tensorflow; // NOLINT (Build/Namespaces)

+0

Ich habe versucht, Ihrem Beispiel zu folgen, aber wenn Sie make ausführen, beschweren Sie sich über den Tensorflow-Namespace ?! Was könnte das Problem sein? – Essa

+0

Ein bisschen spät zu antworten, aber Sie sollten eine neue Frage dafür erstellen. – McAngus