Im trying to fork a (MS Windows) process from matlab
myCaller = ['theExe.exe' ' its arguments' ' &'];
system(myCaller);
However, I cannt achieve a fork.
Eventually, what im trying to do is to start a (MS Windows) process, and close the calling MATLAB routine.
Any suggestions of how to achieve the above?
It's tough; I'm working on the same thing at the moment in Ubuntu.
Basically, MATLAB will sit and wait for the spawned program to complete before it continues with its own process, in spite of the & at the end.
The workaround I have been using has been to make use of a mex-file which creates a separate thread (using pthread). This separate thread starts theExe.exe, while the main mex thread exits.
Some untested hacked-together bits of my code which illustrates the process:
#include "mex.h"
#include <iostream>
#include "pthread.h" /* for threading */
// thread function which calls system call, and waits for it to finish
void *do_thread(void *pid)
{
mexPrintf("In thread\n");
// replace this with your system call - don't know if std::system works on windows?
std::system("your_system_call");
pthread_exit(NULL);
}
// main mex function
void mexFunction (int nlhs, mxArray * plhs[], int nrhs, const mxArray * prhs[])
{
pthread_t thread;
mexPrintf("In main: creating thread\n");
rc = pthread_create(&thread, NULL, do_thread, (void *)v);
return;
}
On Ubuntu, this can be compiled something like:
mex mex_filename.cpp -I/usr/include/ -lpthread -lrt
I admit I don't know how to compile this on Windows, but versions of pthreads does exist for Windows.
Related
I am using UART5 for serial communication from my custom board to my PC. To enable communicating from both CPUs (CM4 and CM7), I use the following configuration in STM32CubeIDE:
So the corresponding initialization is done via the auto-generated code MX_UART5_Init() on CM4. The handle UART_HandleTypeDef huart5 is automatically placed in main() of CM4. Now if I want to send a string to my PC, I can use this HAL function:
HAL_UART_Transmit(&huart5, (const uint8_t*) strg, strLen, timeout);
So far, so good.
The problem is that I cannot call the same function from CM7 because obviously the handle huart5 is unknown on that core. Therefore I've tried to share the handle huart5 via shared memory (SRAM4) to make it known to CM7:
#define HUART ((UART_HandleTypeDef*) (0x30040000UL))
HUART = huart5;
But then the compiler complains that UART_HandleTypeDef is undeclared. Indeed, this typedef is declared in the driver stm32h7xx_hal_uart.h. But when I try to include this file in my corresponding code on CM7, the compiler barfs with hundreds of errors.
In general, what is the proper invocation of HAL functions in case I want to use them on both CPUs for something that's initialized on just one of the cores?
Am I going about serial communication via the dedicated HAL functions from both cores incorrectly?
The problem is that I cannot call the same function from CM7 because obviously the handle huart5 is unknown on that core. Therefore I've tried to share the handle huart5 via shared memory (SRAM4) to make it known to CM7:
That is not true. Your image shows that the UART5 is enabled for CM7 and CM4. In addition, CM4 is designated as the core that will do the initialization of UART5. When the Device Configuration Tool runs it will define huart5 in both cores.
If you look in CM4 and CM7's main.c file you will find:
UART_HandleTypeDef huart5;
To use it outside of main.c simple add the following extern to whatever c file you want to have access to huart5.
extern UART_HandleTypeDef huart5;
I generally add the extern defs for huart handles to the main.h file in each core.
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart4;
extern UART_HandleTypeDef huart3;
extern osEventFlagsId_t MainTaskMasterEventHandle;
extern osEventFlagsId_t debugTaskMasterEventHandle;
extern osTimerId_t sendRxByteToDpmHandle;
extern TIM_HandleTypeDef htim2;
/* USER CODE END EC */
I'm trying to create my own servo.write block in Simulink for Arduino DUE deployment (and External Mode). Before you ask why if there is one available inside the Simulink Arduino Support Package, generally my final goal is to create a block that will use Arduino servo.writeMicroseconds function (there is no out of the box block for this one) but first i want to try with something simple to debug to see if i can get it to work....
I've been using this guide (https://www.mathworks.com/matlabcentral/fileexchange/39354-device-drivers) and one of working examples in there as a template and started modifying it (originally it implemented Digital Output driver). I took the LCT approach.
The the original digitalio_arduino.cpp/h files from the guide (example with digital read/out) were the files I modified as they were working without any issues out-of-the-box. Step by step i made following modifications:
Remove DIO read (leave only write) from CPP and H files
Change StartFcnSpec to digitalIOSetup and make changes in H file so port is always in OUTPUT mode
Include Servo.h library within CPP file and create Servo object
Up to this point, all edits went fine, no compile errors, all header files were detected by Simulink and diode kept blinking as it should so the code actually worked (i ran it in External Mode).
But as soon as i made the final modification and replaced pinMode() with myservo.attach() and digitalWrite() with myservo.write() (of course i changed the data type in writeDigitalPin function from boolean to uint8_T) the code, despite compiling and building without any issue didn't work at all. Specified servo port was completely dead, as it even wasn't initialised. Changing value on S-Function input didn't yield any results.
Of course If i replaced custom block with built in Servo Write block from Hardware Support Package, everything worked fine so its not hardware issue.
I'm completely out of ideas what could be wrong, especially that there are no errors so not even a hint where to look.
Here is the LCT *.m script used for generating S-Function:
def = legacy_code('initialize');
def.SFunctionName = 'dout_sfun';
def.OutputFcnSpec = 'void NO_OP(uint8 p1, uint8 u1)';
def.StartFcnSpec = 'void NO_OP(uint8 p1)';
legacy_code('sfcn_cmex_generate', def);
legacy_code('compile', def, '-DNO_OP=//')
def.SourceFiles = {fullfile(pwd,'..','src','digitalio_arduino.cpp')};
def.HeaderFiles = {'digitalio_arduino.h'};
def.IncPaths = {fullfile(pwd,'..','src'), 'C:\ProgramData\MATLAB\SupportPackages\R2021b\aIDE\libraries\Servo\src'};
def.OutputFcnSpec = 'void writeDigitalPin(uint8 p1, uint8 u1)';
def.StartFcnSpec = 'void digitalIOSetup(uint8 p1)';
legacy_code('sfcn_cmex_generate', def);
legacy_code('sfcn_tlc_generate', def);
legacy_code('rtwmakecfg_generate',def);
legacy_code('slblock_generate',def);
Here is digitalio_arduino.CPP file
#include <Arduino.h>
#include <Servo.h>
#include "digitalio_arduino.h"
Servo myservo;
// Digital I/O initialization
extern "C" void digitalIOSetup(uint8_T pin)
{
//pinMode(pin, OUTPUT);
myservo.attach(pin);
}
// Write a logic value to pin
extern "C" void writeDigitalPin(uint8_T pin, uint8_T val)
{
//digitalWrite(pin, val);
myservo.write(val);
}
// [EOF]
And here is digitalio_arduino.H file
#ifndef _DIGITALIO_ARDUINO_H_
#define _DIGITALIO_ARDUINO_H_
#include "rtwtypes.h"
#ifdef __cplusplus
extern "C" {
#endif
void digitalIOSetup(uint8_T pin);
void writeDigitalPin(uint8_T pin, uint8_T val);
#ifdef __cplusplus
}
#endif
#endif //_DIGITALIO_ARDUINO_H_
As I mentioned I've been using a working example as a reference. So I've modified it step by step to see if maybe there is a point when suddenly some error comes up but everything compiles yet does not work :/
I was wondering maybe if there is an issue with the Servo.h library or the Servo object and did some tinkering with these, like i removed Servo myservo; line of code to see if anything happens and just like expected, i started receiving errors that Servo is not defined. If I did not include Servo.h at all or forget to add IncPath to Servo.h as before compile errors about Servo not being supported symbol or not being able to find Servo.h library - so actually the code seems to be "working" in a way, it seems to have everything it needs to work :/
I also looked at the MathWorks implementation of Servo Write block, the MWServoReadWrite to see how Arduino API is being used and no surprise, it's being used in the same way as I've been trying to. They include Servo.h, they are using servo.attach() and servo.write() to control the servo port. And that's it. Yet for them it works, for me does not :/
When I inspect generated C code that runs on Arduino (with my custom S-Function block in it), it seems that all the functions are placed exactly where they are supposed to be, they receive correct arguments. I expected at least that I'll find a hint in there, i.e. missing code or anything else.
I write CUDA code that I call from MATLAB MEX files. I am not using any of MATLABs GPU libraries or capabilities. My code its just CUDA code that accepts C type variables and I only use mex to convert from mwtypes to C types, then call independent self-written CUDA code.
The problem is that sometimes, specially in development phase, CUDA fails (because I made a mistake). Most CUDA calls are generally surrounded by a call to gpuErrchk(cudaDoSoething(cuda)), defined as:
// Uses MATLAB functions but you get the idea.
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
mexPrintf("GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort){
//cudaDeviceReset(); //This does not make MATLAB release it
mexErrMsgIdAndTxt("MEX:myfun", ".");
}
}
}
While this works as expected, giving errors such as
GPUassert: an illegal memory access was encountered somefile.cu 208
In most cases MATLAB does not release the GPU afterwards. Meaning that even if I change the code and recompile, the next call of the code will result in error:
GPUassert: all CUDA-capable devices are busy or unavailable
somefile.cu firs_cuda_line
The only way of removing this error is restarting MATLAB. This is just annoying and hinders the development/testing process. This is not what happens when I develop in say Visual Studio.
I have tried to cudaDeviceReset() both before and after the error has been raised, but to no avail.
What can I do/try to make MATLAB release the GPU after a GPU runtime error?
I want to parallelize a Python loop on GPU, but I don't want to use pyCUDA, because I need to do lots of thing myself. I am looking for something like OpenACC as in C++ for Python to implement the simple parallelization, but it seems no such thing. So I am thinking just using OpenACC in C++ and then system call a Python script, as in the code below. Will this work? Or is there any simple alternative without using pyCUDA?
void foo(float*parameters){
%%system call python function with parameters as input
}
#pragma acc parallel loop
for ( int i=0; i<n; ++i) {
foo(parameters[i]);
//call on the device
}
No, this wont work. You can't execute a host system call from the device.
For OpenACC device code, you can only call routines having the OpenACC "routine" directive, or a CUDA "device" routine.
I fiddled with this the whole day, so I thought I might make everyone benefit from my experience, please see my answer below.
I first had a problem with running a compiled Mex file within Matlab, because Matlab complained that it couldn't open the shared library libarmadillo. I solved this using the environment variables LD_LIBRARY_PATH and LD_RUN_PATH (DYLD_LIBRARY_PATH and LYLD_RUN_PATH in osx).
The problem remained however, that a simple test file would segfault at runtime even though the exact same code would compile and run fine outside Matlab (not Mex'd).
The segfault seems to be caused by the fact that Matlab uses 64bits integers (long long or int64_t) in its bundled LAPACK and BLAS libraries. Armadillo on the other hand, uses 32bits integers (regular int on a 64bits platform, or int32_t) by default.
There are two solutions; the first one involves forcing Matlab to link to the system's libraries instead (which use ints), the second involves changing Armadillo's config file to enable long longs with BLAS. I tend to think that the first is more reliable, because there is no black-box effect, but it's also more troublesome, because you need to manually install and remember the path of your BLAS and LAPACK libs.
Both solutions required that I stopped using Armadillo's shared libraries and linked/included manually the sources.
To do this, you must simply install LAPACK and BLAS on your system (if they are not already there, in Ubuntu that's libblas-dev and liblapack-dev), and copy the entire includes directory somewhere sensible like in $HOME/.local/arma for example.
Solution 1: linking to system's libraries
From the matlab console, set the environment variables BLAS_VERSION and LAPACK_VERSION to point to your system's libraries. In my case (Ubuntu 14.04, Matlab R2014b):
setenv('BLAS_VERSION','/usr/lib/libblas.so');
setenv('LAPACK_VERSION','/usr/lib/liblapack.so');
You can then compile normally:
mex -compatibleArrayDims -outdir +mx -L/home/john/.local/arma -llapack -lblas -I/home/john/.local/arma test_arma.cpp
or if you define the flag ARMA_64BIT_WORD in includes/armadillo_bits/config.hpp, you can drop the option -compatibleArrayDims.
Solution 2: changing Armadillo's config
The second solution involves uncommenting the flag ARMA_BLAS_LONG_LONG in Armadillo's config file includes/armadillo_bits/config.hpp. Matlab will link to its bundled LAPACK and BLAS libraries, but this time Armadillo won't segfault because it's using the right word-size. Same than before, you can also uncomment ARMA_64BIT_WORD if you want to drop the -compatibleArrayDims.
Compiled with
mex -larmadillo -DARMA_BLAS_LONG_LONG armaMex_demo2.cpp
(In Matlab)
armaMex_demo2(rand(1))
works without segfault.
However, compiled with
mex -larmadillo armaMex_demo2.cpp
(In Matlab)
armaMex_demo2(rand(1))
causes a segfault.
Here, armaMex_demo2.cpp is
/* ******************************************************************* */
// armaMex_demo2.cpp: Modified from armaMex_demo.cpp copyright Conrad Sanderson and George Yammine.
/* ******************************************************************* */
// Demonstration of how to connect Armadillo with Matlab mex functions.
// Version 0.2
//
// Copyright (C) 2014 George Yammine
// Copyright (C) 2014 Conrad Sanderson
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
/////////////////////////////
#include "armaMex.hpp"
void
mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
/*
Input: X (real matrix)
Output: Eigenvalues of X X.T
*/
if (nrhs != 1)
mexErrMsgTxt("Incorrect number of input arguments.");
// Check matrix is real
if( (mxGetClassID(prhs[0]) != mxDOUBLE_CLASS) || mxIsComplex(prhs[0]))
mexErrMsgTxt("Input must be double and not complex.");
// Create matrix X from the first argument.
arma::mat X = armaGetPr(prhs[0],true);
// Run an arma function (eig_sym)
arma::vec eigvals(X.n_rows);
if(not arma::eig_sym(eigvals, X*X.t()))
mexErrMsgTxt("arma::eig_sym failed.");
// return result to matlab
plhs[0] = armaCreateMxMatrix(eigvals.n_elem, 1);
armaSetPr(plhs[0], eigvals);
return;
}