Unfortunally I’ve got the flue, so I’m here at home, alone (not so alone, cats are with me), with some time to spend. Fortunally I still have a blog where to write! 🙂
Sorry guys, I’ve been very busy these times and that’s the reason why I took so long to write again. But I’m here and with your big surprise (or not) I’m writing in English.
So, just to start, I wanna write a little post with two very useful tips that I’ve found many programmers doesn’t know, but I think they should.
And those tips are:
Clipboard ring
Toggle comment
Clipboard Ring
Microsoft calls it Clipboard Ring but, for example the smart guys at JetBrains call it Clipboard History.
What’s it? Actually Visual Studio and for example IntelliJ remembers all code you have copied not only the last one.
With Ctrl+V (Cmd+V) you just obtain the last copied code, but with Ctrl+Shift+V (Windows) or Cmd+Shift+V (Mac) you could cycle around all the previous copies you have done!
Toggle Comment
The toggle comment could be usefull for fast prototyping or fast debugging when you are not sure which choice to do and are evaluating between two alternatives leaving code cleaning for the future.
The block is that:
//* this is your toggle (state on)
<uncommented code>
/*/
<commented code>
//*/
-----
/* this is your toggle (state off)
<commented code>
/*/
<uncommented code>
//*/
Se compiliamo con NVCC in modo che utilizzi un Virtual Code possiamo utilizzare il programma su qualunque architettura di GPU però abbiamo un delay allo startup dell’applicazione, come descritto a pagina 25 del manuale di NVCC di CUDA 7.
CUDA_Compiler_Driver_NVCC.pdf
Che si trova nel seguente direttorio:Â C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0\doc\pdf
“By specifying a virtual code architecture instead of a real GPU, nvcc postpones theassembly of PTX code until application runtime, at which the target GPU is exactlyknown. For instance, the command below allows generation of exactly matching GPUbinary code, when the application is launched on an sm_20 or later architecture.nvcc x.cu –gpu-architecture=compute_20 –gpu-code=compute_20The disadvantage of just in time compilation is increased application startup delay,but this can be alleviated by letting the CUDA driver use a compilation cache (refer to”Section 3.1.1.2. Just-in-Time Compilation” of CUDA C Programming Guide) which ispersistent over multiple runs of the applications.”
Installiamo i sorgenti dove più ci piace, per questo esempio io le metterò sul Desktop.
Poi scarichiamo CMake che al momento della stesura di questo articolo è alla versione 3.3.0. Installiamolo. Io ho utilizzato il Win32 Installer.
Scarichiamo ovviamente il CUDA toolkit dal sito della NVIDIA e installiamolo. Al momento di stesura dell’articolo siamo alla versione 7.0. Io ho installato il Windows 8.1 local installer.
Lanciamo CMake e andiamo a dare il percorso dei sorgenti delle OpenCV e della cartella dove vogliamo generare la solution di Visual Studio 2013 per la compilazione:
Spuntare “Grouped” e “Advanced”, cliccare su “Configure” e scegliere “Visual Studio 12 2013 Win64” e poi “Finished” e aspettare il termine.
Al termine dovremmo vedere “configure done” scritto nella finestra di console di CMake ma la parte centrale probabilmente verrà evidenziata di rosso:
Espandiamo il nodo BUILD nella finestra rossa ed eliminiamo la spunta da BUILD_DOCS.
Nel mio caso l’errore deo Config era il fatto che non trova Doxygen. Semplicemente così dovremmo risolvere il conflitto.
Però io ho eliminato anche la generazione degli esempi per velocizzare un po’ la compilazione togliendo la spunta da BUILD_EXAMPLES
Controlliamo che nel nodo CMAKE il valore di CMAKE_LINKER sia il linker di Visual Studio 2013 (v12).
Controlliamo che nel nodo CUDA non sia selezionato (eventualmente togliamo la sputa da) CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE.
Questo flag server se si eseguono Build in parallelo.
Nel nodo WITH controlliamo che siano selezionati (altrimnenti mettiamo la spunta anche in)Â Â WITH_CUBLAS, WITH_CUDA, WITH_OPENGL.
Intanto che compiliamo con CUDA compiliamo anche le CUDA Basic Linear Algebra Subroutines (cuBLAS) e il supporto per le OPEN_GL.
Ripremiamo “Configure” per fare il refresh e per vedere che questa volta la finestra centrale sia “bianca”.
Vi ricordo che ora è bianca perchè abbiamo tolto la spunta da BUILD_DOCS che cercava Doxygen e non per le altre configurazioni fatte.
Se la finestra centrale è bianca e abbiamo “Configure done” allora è tutto Ok e possiamo cliccare su “Generate” per creare la soluzione Visual Studio.
A questo punto dopo “Generating done” possiamo chiudere CMake e andare ad aprire la solution nella cartella dove abbiamo detto di crearla che nel mio caso è: C:\Users\fabio\Desktop\buildCuda
Aprite la solutione, lanciate ALL_BUILD in Debug o Release e andate a prendere un caffè 🙂
Non vi è bastato vero il caffè? Sul mio PC impiega circa un’ora a Build (i7, 12GB ram, SSD HD).
Una volta finito di Compilare lanciate la INSTALL.
Lanciate INSTALL che trovate in (CMakeTargets) per avere nella directory “install” le dll e librerie appena compilate
Ecco dove troverete le vostre DLL e LIB delle OpenCV compilate con CUDA
Io ora ho compilato in Debug.
Lanciando anche la compilazione in Release vedrete insieme le librerie di debug (*d.dll, *d.lib) assieme a quelle di release (*.dll, *.lib).
OpenCV 2.4.9
Per le OpenCV 2.4.9 il procedimento è praticamente identico, però ho dovuto impostare il CUDA_GENERATION dicendo esplicitamente la mia architettura ‘Kepler‘
Altrimenti avevo l’errore di compilazione:Â Unsupported gpu architecture ‘compute_11’
Ho letto comunque che se si setta l’architettura specifica anche con le OpenCV 3.0 la compilazione è molto più veloce perchè non vengono compilati i file .cu per le altre architatture.
Senza specificarlo invece vengono compilati i .cu per tutte le architatture (GPU): Kepler, Fermi, etc…
E ho dovuto modificare il file NCV.cu (opencv-2.4.9\modules\gpu\src\nvidia\core\NCV.cu), andando ad includere il package “algorithm”:
#include <algorithm>
Altrimenti mi dava l’errore: ‘max’ undefined error.
Per le applicazioni .NET è più difficile avere la riga di codice esatta, soprattutto se non si è tenuto il file .pdb della versione che ha fatto il “crash” a casa del cliente e non vengono caricati correttamente anche i symboli delle classi .NET relative al Framework con cui è stato compilato il programma in question.
Per prima cosa lanciare il caricamento del framework
.loadby sos clr
Comunque anche se si dispone solo del file .dump (vedere come generarlo nell’articolo citato sopra) se lo si apre con WinDBG e si analizzano al suo interno le eccezioni con il comando
!analyze -v
Si può vedere lo stack trace che ci porta al punto di programma incriminato.
Vediamo un esempio.
Il programma C# del nostro esempio è il seguente:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WinDbgCrashTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
badMethod();
}
private void badMethod() {
Object o = null;
String s = o.ToString();
}
}
}
Se lo si lancia andrà in Crash immediato.
Apriamo il suo minidump con WinDBG e lanciamo !analyze -v
Lancirare WinDbg come amministratore in modo che possa scaricare (dal sito di Microsoft) nelle cartelle di sistema i simboli che eventualmente non trova in locale.
Ecco il risultato:
Anche se non è riuscito a caricare i simboli
ci dice che alla riga 2 del metodo badMethod all’interno della classe Form1 si è verificata l’eccezione!
Se diamo a WinDBG il path del .pdb e dei sorgenti che fanno riferimento a quell’eseguibile con il comando
!clrstack
Abbiamo anche più info: il file e la riga dove è avvenuta l’eccezione.
Se un metodo virtuale viene invocato è il tipo di classe a run-time che determina quale metodo verrà invocato.
In un metodo non virutale è, al contrario, il tipo di classe a compile-time che determina quale metodo verrà invocato.
Ad esempio se abbiamo una classe padre come la seguente
namespace VirtaulMethodExamples
{
public class Father
{
public virtual string getVirtaulName() {
return "Father.getVirtaulName()";
}
public string getName() {
return "Father.getName()";
}
}
}
e una classe figlia da essa derivata
namespace VirtaulMethodExamples
{
public class Child: Father
{
public override string getVirtaulName()
{
return "Child.getVirtaulName()";
}
public new string getName()
{
return "Child.getName()";
}
}
}
Nel seguente schenario
Child child = new Child();
Father father = child;
Console.WriteLine(child.getVirtaulName());
Console.WriteLine(child.getName());
Console.WriteLine(father.getVirtaulName());
Console.WriteLine(father.getName());
La penultima riga richiamando un metodo virtual guardal al tipo di classe a run-time (Child) e non al tipo di classe a compile-time (Father) per invocare il metodo.
Contrariamente, l’ultima riga guarda al tipo di classe a compile-time (Father) per invocare il metodo non virtual.
Da notare l’uso della parola chiave “new” nella dichiarazione del metodo getName() nella classe Child per non avere un warning di compilazione in quanto il metodo getName di Child nasconde il metodo getName di Father.