相关疑难解决方法(0)

除了互斥锁或垃圾收集之外的哪些机制可以减慢我的多线程java程序?

问题

我有一段java代码(相关的JDK 1.6.0._22),它实现了无状态,无副作用的自由函数,没有互斥体.然而它确实使用了大量内存(我不知道这是否相关).

在过去,我访问过Sun Laboratories并收集了标准的"性能与线程数"曲线.由于此函数没有互斥锁,因此它有一个很好的图形,尽管随着线程数量的增加垃圾收集也开始了.经过一些垃圾收集调整后,我能够使这条曲线几乎平坦.

我现在在英特尔硬件上做同样的实验.硬件有4个CPU,每个CPU有8个内核和超线程.这给出了64个availableProcessors().不幸的是,"性能与线程数"的曲线很好地适用于1,2,3线程和3线程的大写.在3个线程之后,我可以根据需要添加任意数量的线程,并且性能不会更好

尝试解决问题

我的第一个想法是我曾经愚蠢并在某处引入了一些同步代码.通常要解决此问题,我运行JConsole或JVisualVM,并查看线程堆栈跟踪.如果我有64个线程以3的速度运行,我预计其中有61个会等待进入互斥锁.我没有找到这个.相反,我发现所有线程都在运行:非常慢.

第二个想法是,时间框架可能引入了问题.我用一个虚拟函数替换了我的函数,使用AtomicLong计算到十亿.这与线程数量相当精确:使用64个线程比使用1个线程,我能够快速计算到10亿次,高出64倍.

我认为(绝望开始)也许垃圾收集花了很长时间,所以我调整了垃圾收集参数.虽然这改善了我的延迟变化,但它对吞吐量没有影响:我仍然有64个线程以我期望3运行的速度运行.

我已经下载了英特尔工具VTunes,但我的技巧很弱:它是一个复杂的工具,我还不明白.我订购了说明书:给自己一个有趣的圣诞礼物,但是现在有点太晚了,无法解决我当前的问题

  1. 我可以用什么工具(精神或软件)来提高我对正在发生的事情的理解?
  2. 除了互斥锁或垃圾收集之外的哪些机制可能会减慢我的代码速度?

java performance multithreading garbage-collection

17
推荐指数
2
解决办法
673
查看次数

为什么Skylake比Broadwell-E在单线程内存吞吐量方面要好得多?

我们有一个简单的内存吞吐量基准.对于大块内存,它所做的只是重复记忆.

在几台不同的机器上查看结果(针对64位编译),Skylake机器的性能明显优于Broadwell-E,保持OS(Win10-64),处理器速度和RAM速度(DDR4-2133)不变.我们不是说几个百分点,而是大约2个因素.Skylake配置为双通道,Broadwell-E的结果不会因双/三/四通道而异.

任何想法为什么会这样?随后的代码在VS2015的Release中编译,并报告完成每个memcpy的平均时间:

64位:Skylake为2.2ms,Broadwell-E为4.5ms

32位:Skylake为2.2ms,Broadwell-E为3.5ms.

通过利用多个线程,我们可以在四通道Broadwell-E构建上获得更大的内存吞吐量,这很不错,但是看到单线程内存访问的这种巨大差异令人沮丧.为什么差异如此显着的任何想法?

我们还使用了各种基准测试软件,他们验证了这个简单示例所展示的内容 - 单线程内存吞吐量在Skylake上更好.

#include <memory>
#include <Windows.h>
#include <iostream>

//Prevent the memcpy from being optimized out of the for loop
_declspec(noinline) void MemoryCopy(void *destinationMemoryBlock, void *sourceMemoryBlock, size_t size)
{
    memcpy(destinationMemoryBlock, sourceMemoryBlock, size);
}

int main()
{
    const int SIZE_OF_BLOCKS = 25000000;
    const int NUMBER_ITERATIONS = 100;
    void* sourceMemoryBlock = malloc(SIZE_OF_BLOCKS);
    void* destinationMemoryBlock = malloc(SIZE_OF_BLOCKS);
    LARGE_INTEGER Frequency;
    QueryPerformanceFrequency(&Frequency);
    while (true)
    {
        LONGLONG total = 0;
        LONGLONG max = 0;
        LARGE_INTEGER StartingTime, …
Run Code Online (Sandbox Code Playgroud)

performance benchmarking x86 intel cpu-architecture

12
推荐指数
1
解决办法
1594
查看次数

如何解决AVX加载/存储操作的32字节对齐问题?

我在使用时遇到对齐问题 ymm寄存器,一些代码片段对我来说似乎很好.这是一个最小的工作示例:

#include <iostream> 
#include <immintrin.h>

inline void ones(float *a)
{
     __m256 out_aligned = _mm256_set1_ps(1.0f);
     _mm256_store_ps(a,out_aligned);
}

int main()
{
     size_t ss = 8;
     float *a = new float[ss];
     ones(a);

     delete [] a;

     std::cout << "All Good!" << std::endl;
     return 0;
}
Run Code Online (Sandbox Code Playgroud)

当然,sizeof(float)4在我的架构(英特尔(R)至强(R)CPU E5-2650 V2 @ 2.60GHz),我与编译gcc使用-O3 -march=native标志.当然,错误会随着未对齐的内存访问而消失,即指定_mm256_storeu_ps.我在xmm寄存器上也没有这个问题,即

inline void ones_sse(float *a)
{
     __m128 out_aligned = _mm_set1_ps(1.0f);
     _mm_store_ps(a,out_aligned);
}
Run Code Online (Sandbox Code Playgroud)

我做了什么愚蠢的事吗?解决这个问题的方法是什么?

c++ sse memory-alignment avx c++11

11
推荐指数
2
解决办法
4468
查看次数

为什么numpy不会在非连续数组上短路?

考虑以下简单测试:

import numpy as np
from timeit import timeit

a = np.random.randint(0,2,1000000,bool)
Run Code Online (Sandbox Code Playgroud)

让我们找到第一个的索引 True

timeit(lambda:a.argmax(), number=1000)
# 0.000451055821031332
Run Code Online (Sandbox Code Playgroud)

由于numpy短路,这相当快。

它也适用于连续切片

timeit(lambda:a[1:-1].argmax(), number=1000)
# 0.0006490410305559635
Run Code Online (Sandbox Code Playgroud)

但是,似乎不连续的情况并非如此。我主要对查找最后一个感兴趣True

timeit(lambda:a[::-1].argmax(), number=1000)
# 0.3737605109345168
Run Code Online (Sandbox Code Playgroud)

更新:我的假设是观察到的减速是由于没有短路造成的,这是不准确的(感谢@Victor Ruiz)。实际上,在全False阵列的最坏情况下

b=np.zeros_like(a)
timeit(lambda:b.argmax(), number=1000)
# 0.04321779008023441
Run Code Online (Sandbox Code Playgroud)

我们仍然比不连续的情况快一个数量级。我已经准备好接受维克多(Victor)的解释,即真正的罪魁祸首是复制品(强迫使用复制品的时机.copy()是暗示性的)。之后,是否发生短路就不再重要了。

但是其他步长!= 1会产生类似的行为。

timeit(lambda:a[::2].argmax(), number=1000)
# 0.19192566303536296
Run Code Online (Sandbox Code Playgroud)

问题:为什么在最后两个示例中不进行复制numpy不会短路UPDATE

而且,更重要的是:是否有一种解决方法,即某种方法可以强制numpy更新, 而无需在非连续数组上也进行复制

python numpy short-circuiting

11
推荐指数
2
解决办法
334
查看次数

非临时负载和硬件预取器,它们一起工作吗?

当从连续的内存位置执行一系列_mm_stream_load_si128()调用(MOVNTDQA)时,硬件预取器是否仍会启动,或者我应该使用显式软件预取(使用NTA提示)以获得预取的好处,同时仍然避免缓存污染?

我问这个的原因是因为他们的目标似乎与我相矛盾.流加载将获取绕过缓存的数据,而预取器尝试主动将数据提取到缓存中.

当顺序迭代一个大型数据结构(处理过的数据不会在很长一段时间内被修饰)时,我有必要避免污染chache层次结构,但我不想因频繁出现频繁的~100次循环处罚-fetcher闲置.

目标架构是Intel SandyBridge

performance x86 sse prefetch cpu-cache

9
推荐指数
3
解决办法
2512
查看次数

如何对C++代码的性能进行基准测试?

我开始认真研究算法和数据结构,并有兴趣学习如何比较我可以实现A&DT的不同方式的性能.

对于简单的测试,我可以获得运行之前/之后的时间,运行该事物10 ^ 5次,并平均运行时间.我可以按大小参数化输入,或者对随机输入进行采样,并获得运行时间与输入大小的列表.我可以将其输出为csv文件,并将其输入到pandas中.

我不确定是否有任何警告.我也不确定如何测量空间复杂度.

我正在学习用C++编程.有没有人性化的工具来实现我的目标?

c++ algorithm benchmarking data-structures

9
推荐指数
2
解决办法
5007
查看次数

intel core i7处理器使用哪种缓存映射技术?

我已经了解了不同的缓存映射技术,如直接映射,关联映射和集合关联映射技术,还学习了权衡.但我很好奇现在在intel core i7或AMD处理器中使用了什么.以及这些技术是如何演变的.还有哪些事情需要改进?

x86 amd intel cpu-architecture cpu-cache

8
推荐指数
1
解决办法
2255
查看次数

For循环效率:合并循环

我一直有这个想法,减少迭代次数是方式来使程序更加高效.由于我从未真正确认过,我开始测试这个.

我制作了以下C++程序来测量两个不同函数的时间:

  • 第一个函数执行单个大循环并使用一组变量.
  • 第二个函数执行多个同样大的循环,但每个变量只有一个循环.

完整的测试代码:

    #include <iostream>
    #include <chrono>

    using namespace std;

    int* list1; int* list2;
    int* list3; int* list4;
    int* list5; int* list6;
    int* list7; int* list8;
    int* list9; int* list10;

    const int n = 1e7;

    // **************************************
    void myFunc1()
    {
        for (int i = 0; i < n; i++)
        {
            list1[i] = 2;
            list2[i] = 4;
            list3[i] = 8;
            list4[i] = 16;
            list5[i] = 32;
            list6[i] = 64;
            list7[i] = 128;
            list8[i] = 256;
            list9[i] = …
Run Code Online (Sandbox Code Playgroud)

c++ performance benchmarking loops

7
推荐指数
2
解决办法
851
查看次数

缓存线大小背后的理论和测量是什么?

高速缓存行通常为64 字节,也存在其他大小。

我非常简单的问题是:这个数字背后是否有任何理论,或者它只是背后的工程师无疑所做的大量测试和测量的结果?

不管怎样,我想知道这些是什么(理论,如果有的话,以及决定背后的各种测试)。

cpu cpu-architecture cpu-cache

6
推荐指数
1
解决办法
1484
查看次数

为什么在CNN中使用GEMM的im2col方法比使用SIMD的方向实现方法更高效

卷积层是卷积神经网络(CNN)中计算量最大的部分。目前实现卷积层的常见方法是将图像扩展为列矩阵(im2col)并使用现有的并行通用矩阵乘法(GEMM)库。然而im2col操作需要加载和存储图像数据,并且还需要另一个内存块来保存中间数据。

如果我需要优化卷积实现,我可能会选择用SIMD指令直接实现。这种方法不会产生任何内存操作开销。

非常规律的内存访问模式所带来的好处超过了浪费的存储成本。

来自以下链接,在链接末尾

https://petewarden.com/2015/04/20/why-gemm-is-at-the-heart-of-deep-learning/

所以我希望知道原因。浮点运算可能需要更多指令周期吗?或者输入图像不太大,因此可能会残留在缓存中,并且内存操作不需要访问DDR并且消耗更少的周期。

memory floating-point instruction-set cpu-architecture conv-neural-network

6
推荐指数
1
解决办法
2758
查看次数