我正在使用Tensorflow的C API在并行仿真中进行推理。因为我想要AVX支持,所以从源代码编译了Tensorflow。我将其链接并使用wmake编译了所有内容。
现在,如果我开始正常的(非并行化)仿真运行,则一切正常。但是,如果我将其并行化,则在开始模拟运行后立即得到此错误:
[node134:18796] *** Process received signal ***
[node134:18796] Signal: Segmentation fault (11)
[node134:18796] Signal code: Address not mapped (1)
[node134:18796] Failing at address: (nil)
[node134:18796] [ 0] /lib/x86_64-linux-gnu/libc.so.6(+0x3ef20)[0x7fec1c96ff20]
[node134:18796] [ 1] /home/elias/OpenFOAM/elias-4.1/platforms/linux64GccDPInt32Opt/lib/libtensorflow_framework.so(hwloc_bitmap_and+0x14)[0x7fec01c21534]
[node134:18796] [ 2] /usr/lib/x86_64-linux-gnu/libopen-pal.so.20(opal_hwloc_base_filter_cpus+0x380)[0x7febe59d6b80]
[node134:18796] [ 3] /usr/lib/x86_64-linux-gnu/openmpi/lib/openmpi/mca_ess_pmi.so(+0x2b4e)[0x7febe4902b4e]
[node134:18796] [ 4] /usr/lib/x86_64-linux-gnu/libopen-rte.so.20(orte_init+0x22e)[0x7febe5c2a1de]
[node134:18796] [ 5] /usr/lib/x86_64-linux-gnu/libmpi.so.20(ompi_mpi_init+0x30e)[0x7febffdbc27e]
[node134:18796] [ 6] /usr/lib/x86_64-linux-gnu/libmpi.so.20(MPI_Init+0x6b)[0x7febffddd2ab]
[node134:18796] [ 7] /opt/OpenFOAM/OpenFOAM-4.1/platforms/linux64GccDPInt32Opt/lib/openmpi-system/libPstream.so(_ZN4Foam8UPstream4initERiRPPc+0x1f)[0x7fec1c72843f]
[node134:18796] [ 8] /opt/OpenFOAM/OpenFOAM-4.1/platforms/linux64GccDPInt32Opt/lib/libOpenFOAM.so(_ZN4Foam7argListC1ERiRPPcbbb+0x719)[0x7fec1db36ed9]
[node134:18796] [ 9] tabulatedCombustionFoam(+0x279b8)[0x55fe6eb489b8]
[node134:18796] [10] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xe7)[0x7fec1c952b97]
[node134:18796] [11] tabulatedCombustionFoam(+0x30a0a)[0x55fe6eb51a0a]
[node134:18796] *** End of error message ***
我试图自己修复它,但是到目前为止我看不到任何进展。有人可以识别出此问题的原因吗?
谢谢!
编辑:我不认为代码可能是错误的,因为它在以下情况下有效: -没有并行化 -与标准C API版本一并行,可以下载
以下是“主要”的相关部分:
if(InferenceMode==0)
{
auto t_start_0 = std::chrono::high_resolution_clock::now();
const char* frozenGraphName = "/home/elias/Lr75-57_FPVANN_premix/data/FPV_ANN_tabulated_Standard_500.pb";
const std::string iON = string(input_layer_name);
const char* inputOperationName = iON.c_str();
const std::string oON = string(output_layer_name) + "/BiasAdd";
const char* outputOperationName = oON.c_str();
int no_of_inputs = in_mean.size();
int no_of_outputs = out_mean.size();
int cellsAndPatches = (input_f_zeta_PVNorm.size())/no_of_inputs;
std::vector<int64_t> input_dimensions = {cellsAndPatches,no_of_inputs};
std::vector<int64_t> output_dimensions = {cellsAndPatches,no_of_outputs};
Inference* inf = new Inference();
bool success = inf->doInference(frozenGraphName,inputOperationName,outputOperationName,no_of_inputs,no_of_outputs,input_dimensions,output_dimensions,cellsAndPatches,input_f_zeta_PVNorm,output_real,limit_cores);
delete inf;
auto t_end_0 = std::chrono::high_resolution_clock::now();
auto total_0 = std::chrono::duration<float, std::milli>(t_end_0 - t_start_0).count();
std::cout << "TOTAL INFERENCE TIME C API: " << total_0 << std::endl;
}
这是头文件:
#ifndef INFERENCEC_H
#define INFERENCEC_H
#include "c_api.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <assert.h>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cstdlib>
#include <iostream>
#include <chrono>
#include <ctime>
#include <memory>
#include <unistd.h>
#include <thread>
static void DeallocateBuffer(void* data, size_t)
{
std::free(data);
}
static TF_Buffer* ReadBufferFromFile(const char* file)
{
const auto f = std::fopen(file, "rb");
if (f == nullptr)
{
return nullptr;
}
std::fseek(f, 0, SEEK_END);
const auto fsize = ftell(f);
std::fseek(f, 0, SEEK_SET);
if (fsize < 1)
{
std::fclose(f);
return nullptr;
}
const auto data = std::malloc(fsize);
std::fread(data, fsize, 1, f);
std::fclose(f);
TF_Buffer* buf = TF_NewBuffer();
buf->data = data;
buf->length = fsize;
buf->data_deallocator = DeallocateBuffer;
return buf;
}
static void DeallocateTensor(void* data, std::size_t, void*) // vorher void* arg
{
std::free(data);
}
class Inference
{
public:
bool doInference(const char*,const char*,const char*,int,int,std::vector<int64_t>,std::vector<int64_t>,int,std::vector<float>&,std::vector<float>&,int);
};
#endif // INFERENCEC_H
这是.C文件:
#include "inferenceC.H"
bool Inference::doInference(const char* fgn, const char* iname, const char* oname, int nIn, int nOut, std::vector<int64_t> dimIn,std::vector<int64_t> dimOut, int CP, std::vector<float> &inVals, std::vector<float> &outVals, int maxCores)
{
TF_Buffer* graph_def = ReadBufferFromFile(fgn);
if (graph_def == nullptr)
{
std::cout << "Can't read buffer from file" << std::endl;
}
TF_Graph* graph = TF_NewGraph();
TF_Status* status = TF_NewStatus();
TF_ImportGraphDefOptions* graph_opts = TF_NewImportGraphDefOptions();
TF_GraphImportGraphDef(graph, graph_def, graph_opts, status);
if(TF_GetCode(status)!=TF_OK)
{
std::cout << "ERROR: Unable to import graph " << TF_Message(status) << std::endl;
}
//int num_bytes_in = CP*nIn*sizeof(float);
//int num_bytes_out = CP*nOut*sizeof(float);
TF_DeleteImportGraphDefOptions(graph_opts);
TF_DeleteBuffer(graph_def);
assert((inVals.size()%nIn)==0);
std::cout << "Effective batch size: " << (inVals.size()/nIn) << std::endl;
TF_Output input = {TF_GraphOperationByName(graph, iname), 0};
TF_Output output = {TF_GraphOperationByName(graph, oname), 0};
const std::vector<std::int64_t> dims = {CP,nIn};
std::size_t data_size = sizeof(float);
for (auto i : dims)
{
data_size *= i;
}
auto data = static_cast<float*>(std::malloc(data_size));
std::copy(inVals.begin(), inVals.end(), data);
TF_Tensor* input_value = TF_NewTensor(TF_FLOAT,dims.data(), static_cast<int>(dims.size()),data, data_size,DeallocateTensor, nullptr);
const std::vector<int64_t> outdims = {CP,nOut};
std::size_t outdata_size = sizeof(float);
for (auto i : outdims)
{
outdata_size *= i;
}
TF_Tensor* output_value = nullptr;
std::cout << "Running session..." << std::endl;
TF_SessionOptions* sess_opts = TF_NewSessionOptions();
if(maxCores!=0)
{
uint8_t intra_op_parallelism_threads = maxCores; // for operations that can be parallelized internally, such as matrix multiplication
uint8_t inter_op_parallelism_threads = maxCores; // for operationss that are independent in your TensorFlow graph because there is no directed path between them in the dataflow graph
uint8_t config[]={0x10,intra_op_parallelism_threads,0x28,inter_op_parallelism_threads};
TF_SetConfig(sess_opts,config,sizeof(config),status);
if (TF_GetCode(status) != TF_OK)
{
printf("ERROR: %s\n", TF_Message(status));
}
}
TF_Session* session = TF_NewSession(graph, sess_opts, status);
assert(TF_GetCode(status)==TF_OK);
auto t_start = std::chrono::high_resolution_clock::now();
TF_SessionRun(session, nullptr, &input, &input_value, 1, &output, &output_value, 1, nullptr, 0, nullptr, status);
auto t_end = std::chrono::high_resolution_clock::now();
auto total = std::chrono::duration<float, std::milli>(t_end - t_start).count();
std::cout << "time required for TF_SessionRun: " << total << std::endl;
float* out_vals = static_cast<float*>(TF_TensorData(output_value));
std::vector<float> results(nOut*CP,0);
for(int i=0;i<CP;i++)
{
for(int j=0;j<nOut;j++)
{
results.at(i*nOut+j) = *out_vals;
out_vals++;
}
}
std::cout << "Successfully ran session!" << std::endl;
outVals = results;
TF_CloseSession(session,status);
TF_DeleteSession(session,status);
TF_DeleteSessionOptions(sess_opts);
TF_DeleteStatus(status);
TF_DeleteGraph(graph);
TF_DeleteTensor(output_value);
TF_DeleteTensor(input_value);
return 0;
}
答案 0 :(得分:2)
如以下链接所示,这不是代码错误,而是在当前的master分支上解决了一个Tensorflow问题: