我是深度学习的新手,过去 2 天我一直在尝试在我的电脑上安装 tensorflow-gpu 版本,但徒劳无功。我避免安装 CUDA 和 cuDNN 驱动程序,因为由于许多兼容性问题,几个在线论坛不推荐它。由于我之前已经在使用 python 的 conda 发行版,所以我conda install -c anaconda tensorflow-gpu按照他们的官方网站上写的那样去:https : //anaconda.org/anaconda/tensorflow-gpu。
然而,即使在新的虚拟环境中安装了 gpu 版本后(为了避免与基础环境中安装的 pip 库的潜在冲突),由于某种神秘的原因,tensorflow 似乎甚至无法识别我的 GPU。
我运行的一些代码片段(在 anaconda 提示符下)以了解它无法识别我的 GPU:-
1.
>>>from tensorflow.python.client import device_lib
>>>print(device_lib.list_local_devices())
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 7692219132769779763
]
Run Code Online (Sandbox Code Playgroud)
如您所见,它完全忽略了 GPU。
2.
>>>tf.debugging.set_log_device_placement(True)
>>>a = tf.constant([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
2020-12-13 10:11:30.902956: I tensorflow/core/platform/cpu_feature_guard.cc:142] This
TensorFlow
binary is optimized with oneAPI Deep Neural Network Library (oneDNN)to …Run Code Online (Sandbox Code Playgroud) OpenGL 和 Vulkan 都允许分别使用glMapBuffer和获取指向部分 GPU 内存的指针vkMapMemory。他们都给void*映射的内存一个。要将其内容解释为某些数据,必须将其强制转换为适当的类型。最简单的示例可能是转换为 afloat*以将内存解释为浮点数或向量或类似数组。
似乎任何类型的内存映射在 C++ 中都是未定义的行为,因为它没有内存映射的概念。但是,这并不是真正的问题,因为该主题超出了 C++ 标准的范围。但是,仍然存在一个问题volatile。
在链接的问题中,指针被额外标记为volatile因为它指向的内存内容可以以编译器在编译期间无法预料的方式进行修改。这似乎是合理的,尽管我很少看到人们volatile在这种情况下使用(更广泛地说,这个关键字现在似乎很少使用)。
同时在这个问题中,答案似乎是使用volatile是不必要的。这是因为他们所说的内存是映射使用的mmap,然后msync可以被视为修改内存,这类似于在 Vulkan 或 OpenGL 中显式刷新它。恐怕这不适用于 OpenGL 和 Vulkan。
如果内存被映射为未映射GL_MAP_FLUSH_EXPLICIT_BIT或根本VK_MEMORY_PROPERTY_HOST_COHERENT_BIT不需要刷新,则内存内容会自动更新。即使通过使用手动刷新内存,vkFlushMappedMemoryRanges或者glFlushMappedBufferRange这些函数实际上都没有将映射指针作为参数,因此编译器也不可能知道它们修改了映射内存的内容。
因此,是否有必要将指向映射 GPU 内存的指针标记为volatile?我知道从技术上讲这都是未定义的行为,但我问的是在实际硬件中实际需要什么。
顺便说一下,无论是Vulkan 规范还是OpenGL 规范都没有提到volatile限定符。
编辑:将内存标记为volatile会导致性能开销吗?
我在使用cuda理解NVIDIA gpu架构中的线程时遇到了一些麻烦.
请任何人澄清这些信息:一个8800 gpu有16个SM,每个有8个SP.所以我们有128个SP.
我正在观看斯坦福的视频演示,并且说每个SP都能够在当前运行96个线程.这是否意味着它(SP)可以同时运行96/32 = 3个warp?
此外,由于每个SP可以运行96个线程,并且每个SM都有8个SP.这是否意味着每个SM可以同时运行96*8 = 768个线程?但是如果每个SM一次只能运行一个Block,并且一个块中的最大线程数是512,那么同时运行768个线程并且最多有512个线程的目的是什么?
一个更普遍的问题是:如何将块,线程和warp分配给SM和SP?我读到每个SM一次只能执行一个块,块中的线程被分成warp(32个线程),SP执行warp.
我有GeForce GTX460 SE,所以它是:6 SM x 48 CUDA核心= 288 CUDA核心.众所周知,在一个Warp中包含32个线程,并且在一个块中同时(一次)只能执行一个Warp.也就是说,在单个多处理器(SM)中,即使有48个可用核心,也可以同时只执行一个Block,一个Warp和32个线程?
此外,可以使用threadIdx.x和blockIdx.x来分发具体的Thread和Block的示例.要分配它们,请使用内核<<< Blocks,Threads >>>().但是如何分配特定数量的Warp-s并分发它们,如果不可能那么为什么还要去了解Warps呢?
我知道这听起来很奇怪,但这是我的情景:
我需要进行矩阵 - 矩阵乘法(A(n*k)*B(k*n)),但我只需要对输出矩阵求对角元素.我搜索了cublas库,并没有找到任何能够做到这一点的2级或3级功能.所以,我决定将A的每一行和B的每一列分配到CUDA线程中.对于每个线程(idx),我需要计算点积"A [idx,:]*B [:,idx]"并将其保存为相应的对角线输出.现在因为这个点产品也需要一些时间,我想知道我是否可以在某种程度上调用cublas函数(比如cublasSdot)来实现它.
如果我错过了一些可以直接实现我的目标的cublas函数(只计算矩阵 - 矩阵乘法的对角元素),这个问题可能会被丢弃.
我向那些(几乎)不知道GPU是如何工作的人做了一个演示.我认为说GPU有一千个核心,其中CPU只有四到八个是没有意义的.但我想给观众一个比较的元素.
在使用NVidia的Kepler和AMD的GCN架构几个月后,我很想将GPU"核心"与CPU的SIMD ALU进行比较(我不知道他们是否在英特尔有这个名称).这样公平吗?毕竟,看着汇编级时,这些编程模型有很多共同点(至少是GCN,看看p2-6中的ISA手册).
本文指出Haswell处理器每个周期可以执行32次单精度操作,但我认为有流水线或其他事情可以实现该速率.用NVidia的说法,这款处理器有多少Cuda核心?我会说每个CPU核心有8个用于32位操作,但这只是基于SIMD宽度的猜测.
当然,在比较CPU和GPU硬件时还有许多其他因素需要考虑,但这不是我想要做的.我只需要解释这件事是如何运作的.
PS:非常感谢所有指向CPU硬件文档或CPU/GPU演示的指针!
编辑: 谢谢你的回答,遗憾的是我不得不只选择其中一个.我标记了伊戈尔的答案,因为它最能贴近我最初的问题,并给了我足够的信息来证明为什么这个比较不应该太过分,但是CaptainObvious提供了非常好的文章.
我正在尝试在rootbeer库中运行第一个示例,您可以从此处找到它.
问题是,即使我按照他们的所有说明操作,当我尝试运行Jar时,我收到以下消息
root@ubuserver3:/home/ubuadmin/JavaJars/HelloWordGPU# java -jar HelloWorldGPU.jar
OpenJDK Client VM warning: You have loaded library /usr/lib/libcuda.so.319.37 which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.
Exception in thread "main" java.lang.NullPointerException
at org.trifort.rootbeer.runtime.Rootbeer.run(Rootbeer.java:104)
at ScalarMult.test(ScalarMult.java:13)
at Main.main(Main.java:17)
Run Code Online (Sandbox Code Playgroud)
我不是Linux人员,所以我不明白如何正确执行此命令.我也不明白它们的意思是什么,因为这是我第一次使用GPU编程.但我知道用错误的命令搞乱GPU是一个问题.
任何人都可以对输出有所了解intel_gpu_top吗?具体来说,什么是任务GAM,VS等(手册页没什么帮助.)
比特流忙什么意思?它似乎总是零......
render busy: 45%: ????????? render space: 83/131072
bitstream busy: 0%: bitstream space: 0/131072
blitter busy: 0%: blitter space: 0/131072
task percent busy
GAM: 43%: ????????? vert fetch: 0 (0/sec)
VS: 35%: ??????? prim fetch: 0 (0/sec)
CL: 33%: ??????? VS invocations: 2101845324 (1427552/sec)
SF: 33%: ??????? GS invocations: 0 (0/sec)
VF: 33%: ??????? GS prims: 0 (0/sec)
GAFS: 33%: ??????? CL invocations: 701123988 (475776/sec)
SOL: 32%: ??????? CL prims: …Run Code Online (Sandbox Code Playgroud) 下面的代码执行操作上gpuArrays相同的操作a和b在两种不同的方式.第一部分计算(a'*(a*b)')',第二部分计算a*b*a.然后验证结果是相同的.
%function test
clear
rng('default');rng(1);
a=sprand(3000,3000,0.1);
b=rand(3000,3000);
a=gpuArray(a);
b=gpuArray(b);
tic;
c1=gather(transpose(transpose(a)*transpose(a*b)));
disp(['time for (a''*(a*b)'')'': ' , num2str(toc),'s'])
clearvars -except c1
rng('default');
rng(1)
a=sprand(3000,3000,0.1);
b=rand(3000,3000);
a=gpuArray(a);
b=gpuArray(b);
tic;
c2=gather(a*b*a);
disp(['time for a*b*a: ' , num2str(toc),'s'])
disp(['error = ',num2str(max(max(abs(c1-c2))))])
%end
Run Code Online (Sandbox Code Playgroud)
但是,计算(a'*(a*b)')'速度大约是计算速度的4倍a*b*a.以下是R2018a上Nvidia K20上面脚本的输出(我尝试过不同的版本和不同的GPU,具有相似的行为).
>> test
time for (a'*(a*b)')': 0.43234s
time for a*b*a: 1.7175s
error = 2.0009e-11
Run Code Online (Sandbox Code Playgroud)
甚至更奇怪的是,如果上述脚本的第一行和最后一行是未注释的(它变成一个函数),则两个取较长的时间量(〜1.7S代替〜0.4秒).以下是此案例的输出:
>> test
time for (a'*(a*b)')': 1.717s
time for a*b*a: 1.7153s
error = 1.0914e-11
Run Code Online (Sandbox Code Playgroud)
我想知道是什么导致了这种行为,以及如何在matlab函数内而不是在脚本内部的较短时间内(即~0.4s而不是~1.7s)执行 …
在使用 Apache JMeter 进行性能测试期间,我的初始模型遇到了问题。
错误:分配形状为 [800,1280,3] 的张量并在 /job:localhost/replica:0/task:0/device:GPU:0 上通过分配器 GPU_0_bfc [[Node: Cast = CastDstT=DT_FLOAT, SrcT=DT_UINT8, _device="/job:localhost/replica:0/task:0/device:GPU:0"]] 提示:如果您想在 OOM 发生时查看已分配张量的列表,请将 report_tensor_allocations_upon_oom 添加到 RunOptions for current分配信息。