我开始学习CUDA,我认为计算pi的长数字将是一个很好的介绍性项目.
我已经实现了简单的蒙特卡罗方法,该方法很容易并行化.我只是让每个线程在单位正方形上随机生成点,计算单位圆内有多少点,并使用缩小操作计算结果.
但这当然不是计算常数的最快算法.以前,当我在单线程CPU上进行此练习时,我使用类似Machin的公式来进行计算,以便更快地收敛.对于那些感兴趣的人,这涉及将pi表示为反复数组的总和并使用泰勒级数来评估表达式.
这样一个公式的一个例子:
不幸的是,我发现将这种技术并行化到数千个GPU线程并不容易.问题是大多数操作只是在进行高精度数学运算,而不是对长数据向量进行浮点运算.
所以我想知道,在GPU上计算pi的任意长数字的最有效方法是什么?
所以在像C这样的语言中,内存分为5个不同的部分:OS内核,文本段,静态内存,动态内存和堆栈.像这样的东西:
如果我们在C中声明了一个静态数组,那么你必须事先指定它的大小,然后才能永久修复它.该程序将为阵列分配足够的内存,并按预期将其粘贴在静态数据段中.
但是我注意到在Java中,你可以这样做:
public class Test {
static int[] a = new int[1];
public static void main( String[] args ) {
a = new int[2];
}
}
Run Code Online (Sandbox Code Playgroud)
一切都会像你期望的那样奏效.我的问题是,为什么这在Java中有效?
编辑:所以共识是int[]
Java中的行为int*
与C中的行为更相似.所以作为后续问题,有没有办法在Java中在静态内存中分配数组(如果没有,为什么不呢)?这不会更快地访问这样的阵列吗?EDIT2:^现在这是一个新问题:静态类变量存储在内存中的哪个位置?
我的页面上有一个文件上传框和一个清除按钮.当我按下清除按钮时,我希望清除文件上传框中的文本.
以下适用于Firefox,但不适用于IE(文本保留在那里).这有解决方法吗?
$("#clear").click( function() {
$("#attachment").val("");
//document.myform.attachment.value = "";
})
Run Code Online (Sandbox Code Playgroud)
HTML:
<form name="myform">
<input type="file" name="attachment" id="attachment" />
</form>
<br /><button id="clear">Clear Attachment</button>
Run Code Online (Sandbox Code Playgroud)
我想知道为什么Java对于超类和具有相同名称的实例变量的子类有这种奇怪的行为.
假设我们有以下类定义:
class Parent {
int var = 1;
}
class Child extends Parent {
int var = 2;
}
Run Code Online (Sandbox Code Playgroud)
通过这样做,我们应该隐藏超类的变量var
.如果我们没有明确指定的方式来访问Parent
的var
通过super
电话,那么我们不应该能够访问var
一个孩子的一个实例.
但是当我们有一个演员表时,这个隐藏机制就会破坏:
Child child = new Child();
Parent parent = (Parent)child;
System.out.println(parent.var); // prints out 1, instead of 2
Run Code Online (Sandbox Code Playgroud)
这不完全绕过整个隐藏点吗?如果是这种情况,那么这不会使这个想法完全没用吗?
编辑:我在Java教程中专门提到这篇文章.它提到了
在子类中,超类中的字段不能通过其简单名称引用.相反,必须通过超级...访问该字段
从我在那里读到的内容,似乎暗示Java的开发人员在这方面考虑了某种技术.虽然我同意这是一个相当模糊的概念,但总的来说可能是不好的做法.
我在这里看到这个游戏Flow,它看起来很有趣.
将匹配的颜色与管道连接以创建流程.配对所有颜色,并覆盖整个板,以解决每个难题.但请注意,如果管道交叉或重叠,管道会断裂.
给定一组对(x, y)
,是否有一个算法来解决这个难题,即填写整个网格(假设有一个解决方案),我不知道?
我知道断言可以在运行时启用/禁用,分别用于调试和生成.但是我发现断言也增加了生成的二进制文件的大小(在下面的例子中约为100-200字节).
在C和C++中,我们可以在编译时通过#define NDEBUG
以前执行此操作#include <assert.h>
.
Java编译器有没有办法自动执行此操作?我想将它们留在源代码中以便以后进行调试.但我也不希望生成的二进制文件大于必要的大小(我们有一个大小限制作为设计要求).
C代码:
//#define NDEBUG
#include <assert.h>
int main(void) {
assert(0); // +200 bytes without NDEBUG, 0 with NDEBUG
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Java代码:
public class Test {
public static void main(String[] args) {
assert(System.nanoTime()==0); // increases binary size by about 200 bytes
}
}
Run Code Online (Sandbox Code Playgroud)
回应bn.的答案:
public class Test2 {
public static final boolean assertions = false;
public static void main(String[] args) {
if(assertions) {
assert(System.nanoTime()==0);
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:事实上,在我看来,这种启用/禁用是比运行时更有用的编译时功能.我的意思是,有多少最终用户会启用它们?就程序员而言,在调试过程中,他/她可能会重新编译代码.
这是如何将静态数组存储在Java内存中的后续问题?.
因此,C/C++中的全局变量存储在内存的静态数据段中.但是Java/C++中的静态类变量呢?
它不能是静态数据段,因为您不知道在程序的整个过程中将引用什么/多少类(因为反射).它绝对不是堆栈,因为这没有任何意义.将它存储在堆上也是一种不确定的方式.
假设你有参考A -> B -> C -> D
.当您删除对B
from 的引用时A
,您将留下一个孤立的对象链B -> C -> D
.
将C
与D
被垃圾收集,即使没有办法让他们(因为有没有参考B
)?
我认为GC对此很聪明,并将解决任何此类依赖关系.
但是,我查看了该课程的源代码LinkedList
,发现了与此信念相反的内容.我注意到,当列表被clear()
编辑时,每个链接的所有引用都被显式设置为null
,从而使其成为一个O(n)
操作.这样做有什么理由/好处吗?
我正在读取一个非常大的文件,并从每一行中提取一小部分文本.但是在操作结束时,我的内存很少.在读取文件后,垃圾收集器似乎无法释放内存.
我的问题是:有没有办法释放这段记忆?或者这是一个JVM错误?
我创建了一个SSCCE来证明这一点.它读取1 mb(由于16位编码而在Java中为2 mb)文件并从每行中提取一个字符(~4000行,因此应该是大约8 kb).在测试结束时,仍然使用了完整的2 mb!
最初的内存使用情况:
Allocated: 93847.55 kb
Free: 93357.23 kb
Run Code Online (Sandbox Code Playgroud)
读取文件后立即(在任何手动垃圾收集之前):
Allocated: 93847.55 kb
Free: 77613.45 kb (~16mb used)
Run Code Online (Sandbox Code Playgroud)
这是预料之中的,因为程序正在使用大量资源来读取文件.
然而,我垃圾收集,但不是所有的内存都被释放:
Allocated: 93847.55 kb
Free: 91214.78 kb (~2 mb used! That's the entire file!)
Run Code Online (Sandbox Code Playgroud)
我知道手动调用垃圾收集器不会给你任何保证(在某些情况下它是懒惰的).然而,这发生在我的大型应用程序中,其中文件几乎占用了所有可用内存,并且导致程序的其余部分尽管需要它而耗尽内存.这个例子证实了我怀疑从文件中读取的多余数据没有被释放.
以下是生成测试的SSCCE:
import java.io.*;
import java.util.*;
public class Test {
public static void main(String[] args) throws Throwable {
Runtime rt = Runtime.getRuntime();
double alloc = rt.totalMemory()/1000.0;
double free = rt.freeMemory()/1000.0;
System.out.printf("Allocated: %.2f kb\nFree: %.2f kb\n\n",alloc,free);
Scanner in = new Scanner(new File("my_file.txt"));
ArrayList<String> …
Run Code Online (Sandbox Code Playgroud) java ×6
memory ×3
algorithm ×2
performance ×2
arrays ×1
assert ×1
c ×1
c++ ×1
cuda ×1
file-upload ×1
graph ×1
html ×1
ipc ×1
javascript ×1
jquery ×1
linked-list ×1
linux ×1
oop ×1
pi ×1
static ×1