C++ CPU哈希比GPU快?

C++ CPU哈希比GPU快?,c++,hash,opencl,C++,Hash,Opencl,我想生成一个随机数,并在我的GPU上使用OpenCL和基本代码对其进行哈希运算(它不是对预先给定的纯文本进行哈希运算,而是对随机数进行哈希运算)。 我在我的GPU上使用了所有的哈希,但有一个问题: 当使用OpenCL时,每秒完成的哈希数会降低吗 是的,你听对了,目前只使用CPU比只使用GPU更快。 我的GPU运行速度仅为~10%,而我的CPU运行速度为~100% 我的问题是:这怎么可能,更重要的是,我如何修复它 这是我用来生成伪随机数的代码(在两次运行之间根本不会改变): 从这里调用: void

我想生成一个随机数,并在我的GPU上使用
OpenCL
和基本代码对其进行哈希运算(它不是对预先给定的纯文本进行哈希运算,而是对随机数进行哈希运算)。
我在我的GPU上使用了所有的哈希,但有一个问题:
当使用OpenCL时,每秒完成的哈希数会降低吗

是的,你听对了,目前只使用CPU比只使用GPU更快。
我的GPU运行速度仅为
~10%
,而我的CPU运行速度为
~100%

我的问题是:这怎么可能,更重要的是,我如何修复它

这是我用来生成
伪随机数的代码(在两次运行之间根本不会改变):

从这里调用:

void Miner::Start() {
    std::chrono::system_clock::time_point today = std::chrono::system_clock::now();
    startTime = std::chrono::system_clock::to_time_t(today);
    std::thread tickT(&Miner::ticker, this);
    PostHit();
    GetAPIBalance();
    while (true) {
        std::thread t[32]; //max 32
        hashFound = false;
        if (RequestNewBlock()) {
            for (int i = 0; i < numThreads; ++i) {
                t[i] = std::thread(&Miner::JSEMine, this);
            }
            for (auto& th : t)
                if (th.joinable())
                    th.join();
        }
    }
}

CPU的延迟特性比GPU好得多。也就是说,CPU可以执行一种操作方式,比GPU快很多。这甚至没有考虑CPU->Main RAM->PCIe总线->GDDR5“全局”GPU->GPU寄存器->全局GPU->PCIe总线返回->Main RAM->CPU往返时间(我在这里跳过了一些步骤,比如固定和一级缓存)

GPU比CPU具有更好的带宽特性(前提是数据集可以装入GPU有限的本地内存)。GPU执行SHA256哈希的速度比CPU执行SHA256哈希的速度快

比特币需要数百万、数十亿甚至数万亿的散列才能实现具有竞争力的散列率。此外,计算可以在GPU上进行,而无需与CPU进行大量协作(无需通过PCIe进行缓慢的往返)

这是一个基本设计的问题。CPU被设计成最小化延迟,而GPU被设计成最大化带宽。您的问题似乎是延迟限制(您计算的SHA256哈希太少,GPU无法发挥作用)。32是。。。在我们所说的范围内真的很小

AMD GCN架构在您至少有64个工作项之前甚至不会全速运行,可以说您确实需要256个工作项来最大化44个计算单元中的一个,比如说。。。a R9 290x


我想我想说的是:用11264个工作项(或更多)再试一次,这是GPU设计用于工作的工作项的数量。不是32岁。我从R9上的44个计算单元中得到这个数字290x*4个向量单元/计算单元*64个工作项/向量单元。

最好显示散列计算代码,而不是随机发射代码(这似乎不会造成任何问题)。首先;你应该发一封信。第二不要不断地重新创建生成器-使其保持活动状态,并在调用之间重新使用它(重新创建分发版很好;它们不保存状态,而且价格便宜,但生成器确实保存状态,需要播种(一次)并重新使用-它们的构建成本也很高)。OpenCL适用于矢量化代码(SIMD),SHA256并不是一个完全矢量化的计算。@VTT我会这样做的,等等。注意:只使用时间作为种子(不管分辨率如何)是非常糟糕的,在某种程度上是可以预测的。如果你想要一个合适的不可预测的种子,你想在那里混合其他来源(
std::random_device
将是一个不错的选择-你可以添加其他东西(除了
random_device
,如果你喜欢的话)可能是用户CPU的CPUID、当前进程ID、自启动以来的当前时间、主
main
的地址、当前环境变量的散列值、NIC的MAC地址等—但不要只使用时间……啊,是的,我明白了。因此,归结起来就是GPU正在“挨饿”从工作中(在本例中是随机数到散列)?如果是这样,那么我不明白它是如何挨饿的。CPU可以自己做20kh/s(因此创建一个随机数并对其进行散列)。然后,我认为去掉散列负载应该会增加它可以生成的随机数的数量。这里有很多系统。在CPU可以与GPU通信之前,它需要“固定”其工作的内存。然后它将内存传输到主DDR3(或DDR4),然后PCIe总线将数据传输到GPU。在许多情况下,仅在CPU上对数据进行SHA256哈希运算可能比等待RAM将数据传输到GPU更快(更不用说执行计算了)。您需要“批量处理大量工作”如果你真的想利用GPU。在正常情况下,将所有东西都保存在CPU一级缓存和计算中的速度更快。啊,是的,我明白了。有没有一种简单的方法可以为GPU生成足够的工作?或者说,它会不会花费太长的时间来实现“盈利”呢?真的没有“简单”的方法方法。每种测试方法都需要分析、测试和理解。我的第一种方法是在一个巨大的数组中生成所有随机数(比如让CPU批处理达到100MB+的随机数)然后让GPU尝试散列所有这些。我不知道它是否会更快,但是,你必须自己测试它。仅CPU的方法可能会更快,因为CPU的一级缓存速度非常快…任何使用主内存的方法都会自然地显著降低CPU的速度(包括与GPU通信的方法)啊,好吧。那么我想我暂时把GPU的东西放在一边,直到我对它有了更好的理解:)
void Miner::ticker() {
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
    while (true) {
        Sleep(1000);
        HashesPerSecond = hashes;
        hashes = 0;
        PrintInfo();
    }
}
void Miner::Start() {
    std::chrono::system_clock::time_point today = std::chrono::system_clock::now();
    startTime = std::chrono::system_clock::to_time_t(today);
    std::thread tickT(&Miner::ticker, this);
    PostHit();
    GetAPIBalance();
    while (true) {
        std::thread t[32]; //max 32
        hashFound = false;
        if (RequestNewBlock()) {
            for (int i = 0; i < numThreads; ++i) {
                t[i] = std::thread(&Miner::JSEMine, this);
            }
            for (auto& th : t)
                if (th.joinable())
                    th.join();
        }
    }
}
Miner m(threads);
m.Start();