An efficient (quick) way of entering complex data into Matlab workspace.

10 views (last 30 days)
A HW device stores binary data on disk as an array of 32.5e6 unsigned short values which are then read into Matlab workspace, using either fread or memmapfile. The data is actually complex in nature, arranged as I/Q/I/Q/,,, Our goal is to convert the short values into a complex array so that we may perform FFT and other Matlab operations. The problem is that the conversions to single and then to complex are each very time consuming; please see below.
datasize = 32.5e6;
fileID = fopen('dataFile_uint16.bin', 'r');
temp = fread(fileID, dataSize, 'int16=>int16'); % read file as I & Q; memmapfile is faster...
fclose(fileID);
temp1 = single(temp); % Takes between 100-200 ms.
% NOTE: Matlab does not allow short
% data to be converted to complex
complexArray = temp1(1:2:dataSize) + 1i*temp1(2:2:dataSize); % takes ~550 ms
I have tried alternatives to the last line of code above such as complex(a,b) and reshape instead of indexing, but no real-time savings is noticed. Any suggestions?
A rigourous alternative is to write a mex-file which reads, converts, and returns the data to an mxComplexArray type. However, before enbarking on such a journey, I would like to know if the savings in real-time will justify the effort.
Thank you,
Yisrael Loecher

Accepted Answer

James Tursa
James Tursa on 13 May 2019
Edited: James Tursa on 13 May 2019
Assuming you are using R2018a or later, you might try this FEX submission which can reinterpret real variables as interleaved complex variables without a deep copy:
This might save you some time in your second step, but of course won't save any time associated with that first step of converting the uint16 to single. But if the original data is stored as uint16 you are probably just going to have to live with the time it takes to convert it all to single.
  5 Comments
James Tursa
James Tursa on 14 May 2019
"... I need not worry about column/row array orientation differences ..."
Well, whatever order was written to the file is the order you will get when you read it back in, unless you transpose on the fly as part of the read.
"... a cast from short to single can be performed on the fly ..."
Yes, you could also read 16-bit ints from the file and convert to single on the fly as well, thus having only one copy of the data as single in memory at one time.
James Tursa
James Tursa on 1 Jul 2020
Edited: James Tursa on 1 Jul 2020
See also this FEX submission, which contains freadcomplex and fwritecomplex mex routines for reading and writing interleaved complex data files directly in R2018a or later without the need for extra data copies:

Sign in to comment.

More Answers (1)

Jan
Jan on 13 May 2019
Edited: Jan on 13 May 2019
What about avoiding the conversion from int16 to single by doing this on the fly:
temp = fread(fileID, dataSize, 'int16=>single');
Then maybe it is cheaper to import the real and imaginary data separately:
datasize = 32.5e6;
fileID = fopen('dataFile_uint16.bin', 'r');
realX = fread(fileID, dataSize, 'int16=>single', 2);
fseek(fid, 'bof', 2);
imagX = fread(fileID, dataSize, 'int16=>single', 2);
fclose(fileID);
X = realX + 1i * imagX;
Is this faster?
What about:
datasize = 32.5e6;
fileID = fopen('dataFile_uint16.bin', 'r');
tmp = fread(fileID, [2, datasize/2], 'int16=>single');
fclose(fid);
X = tmp * [1; 1i];
  4 Comments
Jan
Jan on 13 May 2019
"Interleaved numerical arrays" sounds like the optimal solution, if you import the data in a Mex function.
Yisrael Loecher
Yisrael Loecher on 14 May 2019
Jan,
I am only now aware of the change that went on under the Matlab hood in R2018a, concerning how complex data (I,Q) is stored in memory. James (below) seems to be an expert on what was before the change, and what is now after the change. I'll be looking into it...

Sign in to comment.

Products


Release

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!