2014-05-12 5 views
3

에 의해 재 할당을 방지하기 위해 편집 : 에서 장소 나는 아마도 거대한 행렬의 첫 번째 요소를 증가,이 경우, 함수의 기능을 래핑 할 기록 중 복사

>> tic; A=zeros(100000000,1); toc; 
Elapsed time is 0.324779 seconds. 
>> tic; A(1)=A(1)+1; toc; A(1) 
Elapsed time is 0.000011 seconds. 
ans = 
    1 

는 그 증가는 것 고려 더 복잡하고 코드 집약적 인 작업이되어야합니다. 따라서, 나는 함수에서 그것을 포장하기로 결정

function A = speedTest(A) 
    A(1)=A(1)+1; 
end 
>> tic; A=speedTest(A); toc; A(1) 
Elapsed time is 0.366090 seconds. 
ans = 
    2 

이 강하게은, 그러나 그것은 필요는 없습니다 복사 제안; 즉 Matlab은 (1) A가 동일한 문장에서 덮어 쓰여진다는 것, (2) A의 데이터가 다른 변수와 공유되지 않는다는 것을 발견 할 수 있습니다. 그러나 분명히 그렇게하지는 않습니다. Working with preallocated arrays in Matlab's mex function

#include <matrix.h> 
#include <mex.h> 

#include <iostream> 

void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) { 
    mxUnshareArray(const_cast<mxArray *>(argin[0]), true); 
    double *data = (double *)mxGetData(argin[0]); 
    data[0] = data[0]+1; 
} 

그러나이 오류가 발생합니다 : 여기에 OP에 의해 제안

그래서 솔루션은 해킹을하는 것입니다

mexSpeedTest.cpp: In function ‘void mexFunction(int, mxArray**, int, const mxArray**)’: 
mexSpeedTest.cpp:7:54: error: ‘mxUnshareArray’ was not declared in this scope 

mxUnshareArray (에 const_cast (argin [0]), true);

mxUnshareArray가 Matlab 8.1.0.604 (R2013a)에서 제거되었다고 가정합니다. 내 버전. 또한 단순히 줄을 제거 할 수 있으며,이 빠르게 작동합니다

>> tic; mexSpeedTest(A); toc; A(1) 
Elapsed time is 0.000061 seconds. 
ans = 
    3 
>> 

을 불변 오른쪽 값을 갖는 matlab에의 규칙을 나누기 그러나. 불행히도 함수의 기능을 래핑하여 코드를 정리하거나 쓸데없는 속도 저하를 허용하지 않으려합니다. 여기서 for-loop 함수를 사용하는데, 여기서는 이미 C++과 mex로 파트를 최적화하려고 시도했습니다.

하나 개의 솔루션이 OO 통해 해결할 수, 즉 : 빠르지 만

classdef incrementabledata < handle 
    properties 
     A=[] 
    end 
    methods 
     function HB=incrementabledata() 
      HB.A = zeros(100000000,1); 
     end 
     function increment(HB) 
      HB.A(1)=HB.A(1)+1; 
     end 
    end 
end 

하지 동등하게 빨리 풀어 베어 증가로; 데이터가 복사되지 않았다고 가정합니다. 또한 많은 상용구 코드입니다.

tic; AA = incrementabledata(); toc 
Elapsed time is 0.005504 seconds. 
tic; AA.increment(); toc; AA.A(1) 
Elapsed time is 0.003939 seconds. 
ans = 
    1 

내 질문이 졸이다 : (1) 그것은 매트랩 참조 구조에 의해 패스의 어떤 종류의 일을하거나 복사 편집없이 출력에 대한 입력 인수를 전달 할 수 있습니까? (2) 왜 mxUnshareArray가 없습니까? 및 (3) mxUnshareArray를 사용하는 경우 A 버전의 함수가 공유되지 않으므로 작업 영역의 A와 다른 버전이되어 "시뮬레이션"참조가 허용되지 않습니다.

내가 @Peters 솔루션이 유효 속도와 깨끗한 코드 :

답변을 원하기 때문에 내가 부탁 해요. 이 속도에서

#include <matrix.h> 
#include <mex.h> 

#include <iostream> 

extern "C" bool mxUnshareArray(mxArray *array_ptr, bool noDeepCopy); 

void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) { 
    mxUnshareArray(const_cast<mxArray *>(argin[0]), true); 
    double *data = (double *)mxGetData(argin[0]); 
    data[0] = data[0]+1; 
} 

결과 :

>> tic; unsharedMexSpeedTest(A); toc; A(1) 
Elapsed time is 0.000119 seconds. 
ans = 
    4 

여전히 베어 솔루션보다 ~ 10 배 느린 나는 모든 데이터를 복사하지 않는 것 같습니다 것을 추가 할, 즉,이 코드 .나는이 함수 호출 오버 헤드로 인해, 그리고 실제 작업이 더 많은 CPU - 사이클을 걸릴 때 상대 속도 손실이 덜 악화된다고 가정하고 있습니다.

답변

4

mxUnshareArray()은 문서화되지 않았습니다. 이는 프로토 타입이 MATLAB 헤더 파일에 선언되지 않았 음을 의미합니다. 그러나 상징은 여전히 ​​사용할 수 있어야합니다. 컴파일러가 호출을 작성하는 방법을 알 수 있도록 함수의 프로토 타입을 직접 작성하면됩니다.

B = A; 
mexSpeedTest(A); 
A(1) 
B(1) 

변수가 본 :

extern "C" bool mxUnshareArray(mxArray *array_ptr, bool noDeepCopy); 

은 "공유 해제"매우 기괴한 일을에서이 유지됩니다 : 당신이 그것을 호출 할 필요가 어디에 (전역 범위에서) 파일의 상단에이 넣어 mexSpeedTest의 입력은 정확하게 A입니다. MEX 함수 호출을 위해 여분의 사본이 만들어지지 않으므로 mxUnshareArray이 원하는 것을 할 것입니다.

+0

좋은 점은 mxUnshareArray 함수 정의를 읽었습니다. – Herbert

+0

이것은 OP (질문 3)의 "예"에서 특히 효과가있는 것으로 보입니다. 이것을 OP에 추가했습니다. – Herbert