2016-07-24 1 views
2

내가 C++ 코드 다음 한 느린C++ AMP는

float Neuron::feedForward(std::vector<Neuron>& previousLayer){ 
float sum=0.0f; 
extent<1> e((int)previousLayer.size()); 

std::vector<float> ops(previousLayer.size()); 
for (int i = 0; i<(int)previousLayer.size(); i += 1) { 
    ops[i] = previousLayer[i].getOutput(); 
} 

array_view<const float, 1>_outputs(e, ops); 
array_view<const float, 1>_weigths(e, weigths); 
array_view<float> _sum(e); 
_sum.discard_data(); 


parallel_for_each(e, [=](index<1> idx) restrict(amp) { 
    _sum[idx] = _outputs[idx] * _weigths[idx]; 

}); 

for (int i = 0; i < e[0]; i += 1) { 
    sum += _sum[i]; 
} 

output=Neuron::transferFunction(sum); 
return output; 

};

이제 프로그램이 매우 느리게 코드를 실행합니다. 단지 몇 밀리 초가 느리지 만 실제 시간은 더 느립니다.

I는 또한 AMP 코드 내부 합 (에만 변경)하도록 시도 :

array_view<float> _sum(1); 
_sum.discard_data(); 

... 

parallel_for_each(e, [=](index<1> idx) restrict(amp) { 
_sum[0] += _outputs[idx] * _weigths[idx]; 

을});

... 

/*for (int i = 0; i < e[0]; i += 1) { 
sum += _sum[i]; 
} 
*/ 

output=Neuron::transferFunction(_sum[0]); 

결국 코드는 다음과 같습니다. 천천히, 손 계산기를 사용하면 더 빠를 것입니다. 이제 질문은 : 왜? 나는 2000의 무게를 가진 뉴런을 가지고 있다면, GPU가 모든 것을 계산하게하는 것이 좋을 것이라고 생각했다. 내가 누락 된 것이 있습니까? 아니면 OpenCL 또는 CUDA를 배워야합니까?

추신. slownes는 정말로 나쁘다. 100 000 번 이상 걸리는 것처럼 (같은 시간에 20 000 신경망을 10 번 계산할 수 있습니다. AMP를 사용하면 정확히 2 개의 동일한 네트워크를 계산할 수 있습니다.)

+0

parallel_for_each 블록 다음에 e에 동기화 호출을 추가 할 수 있습니다. C++ AMP 자습서 (https://msdn.microsoft.com/en-us/magazine/hh882446.aspx)에 따르면 동기화가 자동으로 수행되어야합니다. 그러나 synchronize()를 명시 적으로 호출하지 않으면 예외가 발생합니다. – hacoo

+0

AMP 사용법을 잘 모른다고 생각합니다. 스칼라 _sum [0]에 제품 합계를 누적하려고합니다. 이 권리를 이해한다면, 생성 된 코드가 모든 제품을 sum [0] ("많은 통신")을 보유하고있는 특정 프로세서로 보내고/또는 해당 합계의 모든 업데이트를 강제로 글로벌 잠금 (" 잠금 장치가 많이 있음 "). 둘 다 효율적이지 않습니다. 데이터 병렬 프로그래밍, 기법 및 함정에 대해 읽은 후 AMP에 대한 프로그램을 수정하기 위해 지식을 사용하는 것이 좋습니다. –

+0

전자에서 동기화를 호출 할 수 있는지 여부는 알 수 없지만 _sum에는 std :: 예외가 트리거되지 않습니다.가능한 랩톱에서 실행되기 때문에 GPU는 잠자기 모드 상태이고 AMP가 CPU로 돌아갑니다. 내 CPU 사용률이 ~ 10 %이지만 내 컴퓨터의 스레드 중 하나가 해당 기능의 90 %를 실행 중임을 나타냅니다. – Nyxeria

답변

1

sum[0]을 사용하는 코드는 많은 스레드가 동시에 업데이트 할 때 잘못된 결과를 나타냅니다. sum[0]

순진 구현은 작동해야하지만 GPU에서 데이터를 이동하는 데 상당한 복사 오버 헤드가 있고 계산 속도는 매우 낮기 때문에 매우 비효율적입니다.

그러나 느린 속도를 내기 위해서는 CPU의 WARP 가속기에서 실행 중일 수 있습니다. 다음 코드를 사용하여 사용 가능한 가속기를 확인할 수 있습니다.

https://ampbook.codeplex.com/SourceControl/latest#Samples/ShowAmpDevices/ShowAmpDevices.cpp

은 당신이 여기서 뭘하고있는 것은 감소이다. 이 작업을 GPU에서 효율적으로 수행하는 방법에 대한 많은 기사가 있습니다. CodePlex에는 여러 구현을 보여주는 C++ AMP 코드가 있습니다.

C++ AMP: Accelerated Massive Parallelism with Microsoft Visual C++

그들은 코드와 관련된 책에서 완전히 설명됩니다.

+0

_sum [0]은 테스트 중 하나 였고 _sum [idx]도 시도했습니다. 이것이 아직 최적의 코드는 아니지만 AMP를 배우기위한 간단한 블록입니다 (나중에 GPU로 데이터를 이동하고 거기에서 모든 것을 계산할 계획이지만 나중에 이것을 사용하여 프로세스를 배웁니다). GPU를 직접 선택할 수있는 코드를 GeForce 570에 추가했습니다. 링크에서 코드를 시도했는데 장치에 다음과 같이 표시됩니다. 전용 메모리 : 1.2MB, display = true, is_debug 및 is_emulated가 모두 거짓이며 제한적이며 배정도. AMP에 문제가있는 경우 CUDA를 사용해 보겠습니다. – Nyxeria

관련 문제