Intel VTune Results Understanding - Naive Questions
<p>My application I want to speedup performs element-wise processing of large array (about 1e8 elements).</p>

<p>​The processing procedure for each element is very simple and I suspect that bottleneck could be not CPU but DRAM bandwidth.
​So I decided to study one-threaded version at first.</p>

<p>The system is: Windows 10 64bit, 32 GB RAM, Intel Core i7-3770S Ivybridge 1.10 GHz 4 cores, Hyperthreading enabled</p>

<h1>Concurrency analysis</h1>

<pre><code>Elapsed Time:   34.425s
    CPU Time:   14.908s
        Effective Time: 14.908s
            Idle:   0.005s
            Poor:   14.902s
            Ok: 0s
            Ideal:  0s
            Over:   0s
        Spin Time:  0s
        Overhead Time:  0s
    Wait Time:  0.000s
        Idle:   0.000s
        Poor:   0s
        Ok: 0s
        Ideal:  0s
        Over:   0s
    Total Thread Count: 2
    Paused Time:    18.767s
</code></pre>

<h1>Memory Access Analysis</h1>

<p>Memory Access Analysis provides different CPU times for three consecutive  runs on the same amount of data
​Actual execution time was about 23 seconds as Concurrency Analysis says.</p>

<pre><code>Elapsed Time:   33.526s
    CPU Time:   5.740s
    Memory Bound:   38.3%
        L1 Bound:   10.4%
        L2 Bound:   0.0%
        L3 Bound:   0.1%
        DRAM Bound: 0.8%
            Memory Bandwidth:   36.1%
            Memory Latency: 60.4%
    Loads:  12,912,960,000
    Stores: 7,720,800,000
    LLC Miss Count: 420,000
    Average Latency (cycles):   15
    Total Thread Count: 4
    Paused Time:    18.081s

Elapsed Time:   33.011s
    CPU Time:   4.501s
    Memory Bound:   36.9%
        L1 Bound:   10.6%
        L2 Bound:   0.0%
        L3 Bound:   0.2%
        DRAM Bound: 0.6%
            Memory Bandwidth:   36.5%
            Memory Latency: 62.7%
    Loads:  9,836,100,000
    Stores: 5,876,400,000
    LLC Miss Count: 180,000
    Average Latency (cycles):   15
    Total Thread Count: 4
    Paused Time:    17.913s

Elapsed Time:   33.738s
    CPU Time:   5.999s
    Memory Bound:   38.5%
        L1 Bound:   10.8%
        L2 Bound:   0.0%
        L3 Bound:   0.1%
        DRAM Bound: 0.9%
            Memory Bandwidth:   57.8%
            Memory Latency: 37.3%
    Loads:  13,592,760,000
    Stores: 8,125,200,000
    LLC Miss Count: 660,000
    Average Latency (cycles):   15
    Total Thread Count: 4
    Paused Time:    18.228s
</code></pre>

<p>As far as I understand the Summary Page, the situation is not very good.</p>

<p>The paper <a href="https://software.intel.com/en-us/articles/finding-your-memory-access-performance-bottlenecks" rel="nofollow noreferrer">Finding your Memory Access performance bottlenecks</a> says that the reason is so-called false sharing. But I do not use multithreading, all processing is performed by  just one thread.</p>

<p>From the other hand according to Memory Access Analysis/Platform Page DRAM Bandwidth is not bottleneck.</p>

<p>So the questions are</p>

<ol>
<li>Why CPU times metric values are different for Concurrency Analysis and Memory Access Analysis</li>
<li>What is the reason of bad memory metrics values, especially for L1 Bound?</li>
</ol>

<p>The main loop is lambda function, where</p>

<ul>
<li>tasklets: std::vector of simple structures that contain coefficients for data processing</li>
<li>points: data itself, Eigen::Matrix</li>
<li>projections: Eigen::Matrix, array to put results of processing into  </li>
</ul>

<p>The code is:
</p>

<pre><code>#include &lt;iostream&gt;
#include &lt;future&gt;
#include &lt;random&gt;

#include &lt;Eigen/Dense&gt;

#include &lt;ittnotify.h&gt;

using namespace std;

using Vector3 = Eigen::Matrix&lt;float, 3, 1&gt;;
using Matrix3X = Eigen::Matrix&lt;float, 3, Eigen::Dynamic&gt;;

uniform_real_distribution&lt;float&gt; rnd(0.1f, 100.f);
default_random_engine gen;

class Tasklet {
public:
    Tasklet(int p1, int p2)
        :
        p1Id(p1), p2Id(p2), Loc0(p1)
    {
        RestDistance = rnd(gen);
        Weight_2 = rnd(gen);
    }
    __forceinline void solve(const Matrix3X&amp; q, Matrix3X&amp; p)
    {
        Vector3 q1 = q.col(p1Id);
        Vector3 q2 = q.col(p2Id);
        for (int i = 0; i &lt; 0; ++i) {
            Vector3 delta = q2 - q1;
            float norm = delta.blueNorm() * delta.hypotNorm();
        }
        Vector3 deltaQ = q2 - q1;
        float dist = deltaQ.norm();
        Vector3 deltaUnitVector = deltaQ / dist;
        p.col(Loc0) = deltaUnitVector * RestDistance * Weight_2;
    }

    int p1Id;
    int p2Id;
    int Loc0;
    float RestDistance;
    float Weight_2;
};

typedef vector&lt;Tasklet*&gt; TaskList;

void
runTest(const Matrix3X&amp; points, Matrix3X&amp; projections, TaskList&amp; tasklets)
{
    size_t num = tasklets.size();
    for (size_t i = 0; i &lt; num; ++i) {
        Tasklet* t = tasklets[i];
        t-&gt;solve(points, projections);
    }
}

void
prepareData(Matrix3X&amp; points, Matrix3X&amp; projections, int numPoints, TaskList&amp; tasklets)
{
    points.resize(3, numPoints);
    projections.resize(3, numPoints);
    points.setRandom();
    /*
    for (int i = 0; i &lt; numPoints; ++i) {
    points.col(i) = Vector3(1, 0, 0);
    }
    */
    tasklets.reserve(numPoints - 1);
    for (int i = 1; i &lt; numPoints; ++i) {
        tasklets.push_back(new Tasklet(i - 1, i));
    }

}

int
main(int argc, const char** argv)
{
    // Pause VTune data collection
    __itt_pause();
    cout &lt;&lt; "Usage: &lt;exefile&gt; &lt;number of points (in thousands)&gt; &lt;#runs for averaging&gt;" &lt;&lt; endl;

    int numPoints = 150 * 1000;
    int numRuns = 1;
    int argNo = 1;

    if (argc &gt; argNo) {
        istringstream in(argv[argNo]);
        int i;
        in &gt;&gt; i;
        if (in) {
            numPoints = i * 1000;
        }
    }
    ++argNo;
    if (argc &gt; argNo) {
        istringstream in(argv[argNo]);
        int i;
        in &gt;&gt; i;
        if (in) {
            numRuns = i;
        }
    }
    cout
        &lt;&lt; "Running test" &lt;&lt; endl
        &lt;&lt; "\t NumPoints (thousands): " &lt;&lt; numPoints / 1000. &lt;&lt; endl
        &lt;&lt; "\t # of runs for averaging: " &lt;&lt; numRuns &lt;&lt; endl;

    Matrix3X q, projections;
    TaskList tasklets;

    cout &lt;&lt; "Preparing test data" &lt;&lt; endl;

    prepareData(q, projections, numPoints, tasklets);

    cout &lt;&lt; "Running test" &lt;&lt; endl;

    // Resume VTune data collection
    __itt_resume();
    for (int r = 0; r &lt; numRuns; ++r) {
        runTest(q, projections, tasklets);
    }
    // Pause VTune data collection
    __itt_pause();

    for (auto* t : tasklets) {
        delete t;
    }

    return 0;
}
</code></pre>

<p>Thank you.</p>