我正在整理一个在Matlab MEX函数中利用parallelism features in C++17/20的最小示例。我能够从Matlab编译和运行mex函数,但当我将C++ STL函数的execution policy设置为“par”而不是“seq”时,Matlab给出了运行时链接投诉。代码和错误消息如下:
test.m(Matlab顶级脚本):
vec_in = zeros(5);
coeff = 0.05;
vec_out = test_mex_gateway(vec_in, coeff);
测试_墨西哥_网关. cpp(Matlab的C++接口):
#include "mex.h"
extern void test_execute(float *array_in, float *array_out, const size_t vec_size, const float coeff);
void mexFunction( int nlhs,
mxArray *plhs[],
int nrhs,
const mxArray *prhs[] )
{
// Check for proper number of input and output arguments
if( nrhs != 2 )
{
mexErrMsgTxt( "3 input arguments required: input_data, coeff" );
}
if( nlhs > 2 )
{
mexErrMsgTxt( "Too many output arguments." );
}
const mwSize *matlab_data_dims_in;
mwSize matlab_data_dims_out[1];
// Input Parameters
float *input_data = (float *) mxGetData(prhs[0]);
float coeff = mxGetScalar(prhs[1]);
// Get dimensions
matlab_data_dims_in = mxGetDimensions(prhs[0]);
const int vec_len = matlab_data_dims_in[1];
// Set output data dimension
matlab_data_dims_out[0] = vec_len;
// Output data
plhs[0] = mxCreateNumericArray(1, matlab_data_dims_out, mxSINGLE_CLASS, mxREAL);
float *output_data = (float *) mxGetData(plhs[0]);
test_execute(input_data, output_data, vec_len, coeff);
}
test_execute. cpp(这是进行实际C++ STL调用的位置):
#include <execution> // std::execution::*
#include <numeric> // std::exclusive_scan()
void test_execute(float *array_in, float *array_out, const size_t vec_size, const float coeff)
{
std::exclusive_scan
(
std::execution::par, // std::execution::seq works here for Mex call, par does not
array_in,
array_in + vec_size,
array_out,
0.0f,
[coeff](float a, float b)
{
float ret = a + b + coeff;
return ret;
}
);
}
我还有一个独立的main函数来替换Mex Package 器,以执行纯C++测试test_standalone.cpp:
#include <vector>
#include <iostream>
size_t VEC_NUM_ELEM = 10;
extern void test_execute(float *array_in, float *array_out, const size_t vec_size, const float coeff);
int main(int argc, char **argv)
{
if (argc != 2)
{
std::cout << "Try: " << argv[0] << "<coeff>" << std::endl;
return -1;
}
const float coeff = std::stof(argv[1]);
std::cout << "Coeff: " << coeff << std::endl;
float __attribute__ ((aligned (64))) *vec1_array = (float *)malloc(VEC_NUM_ELEM * sizeof(float));
float __attribute__ ((aligned (64))) *vec2_array = (float *)malloc(VEC_NUM_ELEM * sizeof(float));
for (unsigned i = 0; i < VEC_NUM_ELEM; i++)
{
vec1_array[i] = static_cast<float>(i);
}
test_execute(vec1_array, vec2_array, VEC_NUM_ELEM, coeff);
return 0;
}
下面是我如何构建和链接build.sh:
#!/bin/bash
rm *.o
rm *.exe
rm *.mexa64
cstd=c++17
gpp910=/home/m/compilers/bin/g++
tbblib=/home/m/reqs/tbb/lib/intel64/gcc4.8
echo "Building test_execute.cpp..."
$gpp910 -std=$cstd -I/home/m/reqs/tbb/include -L$tbblib -ltbb -Wl,rpath=$tbblib -c test_execute.cpp -fPIC
echo "Building test_standalone.cpp..."
$gpp910 -std=$cstd -L$tbblib test_execute.o test_standalone.cpp -o test_standalone.exe -ltbb
echo "Building test_mex_gateway.cpp..."
mex test_execute.o test_mex_gateway.cpp -L$tbblib -ltbb
并行STL调用需要链接到英特尔TBB(线程构建模块),因此在运行Matlab调用test.m或运行test_standalone. exe之前,我运行:
导出LD_库路径=/home/m/reqs/tbb/lib/英特尔64/gcc4.8:$LD_库路径
我还确保在运行时提供与我们使用构建的愚者版本相关联的C++库:
导出LD_LIBRARY_PATH=/home/m/编译器/lib 64:$LD_LIBRARY_PATH
当我运行test_standalone.exe时,无论我在std::exclusive_scan上将执行策略设置为“par”还是“seq”,一切都正常运行。当运行test.m时,如果“seq”被编译,我可以无错误运行。如果“par”被编译,Matlab在运行时抱怨链接问题:
- 无效的MEX文件“test_mex_gateway.mexa64”:测试_墨西哥_网关.墨西哥64:未定义符号:_ZN3tbb10接口78内部20隔离区域内ERNS1_13委派基础El *
我怀疑这是一个应该与TBB相关联的功能,我证实了这一点:
英特尔®}| grep基准El
0000000000028 a30 T _ZN3tbb10接口78内部20隔离区域内ERNS1_13代理基础El
000000000005 ed 70 r ZN 3 tbb 10接口78内部20隔离区域内ERNS1_13委派基础E1 $$LSDA
我确认Matlab的LD_LIBRARY_PATH具有我在上述“export..”中提供的到此库的路径。
我试图确保我的库出现在Matlab从终端启动后添加到LD_LIBRARY_PATH的许多以Matlab为中心的路径之前。
我尝试通过一个-Wl,rpath=到链接器的通道来烘焙链接库的路径<path_to_tbb.so>。
两天后,我还是搞不懂为什么Matlab会有这个特殊的运行时问题,尤其是纯C++版本没有。
RHEL 7.9版本
Matlab R2020a
合同通用条款第9.1.0条
TBB(英特尔线程构建模块)2020.3
1条答案
按热度按时间3xiyfsfu1#
看起来Matlablibtbb.so的安装中包含了一个www.example.com版本,据我所知,当启动一个Mex文件时,Matlab将首先使用它自己的库,不管你的LD_LIBRARY_PATH顺序如何。这就是为什么我在运行Mex文件时会出现问题,而在运行纯C++文件时不会出现问题。从Matlab的安装目录中删除libtbb.so会允许运行时链接找到 my libtbb的版本,而且我能够毫无错误地运行。感谢Cris Luengo为我指明了正确的方向。