有人可以提供一些关于我如何通过多线程减少循环运行时的建议吗?假设我还有两个名为'a'和'b'的向量。
for (int j = 0; j < 8000; j++){
// Perform an operation and store in the vector 'a'
// Add 'a' to 'b' coefficient wise
}
这个for循环在我的程序中执行了很多次。上面for循环中的两个操作已经过优化,但它们只在一个核心上运行。但是,我有16个核心,并且想要使用它们。
我尝试按如下方式修改循环。我没有向量'a',而是有16个向量,并假设第i个被称为a [i]。我的for循环现在看起来像
for (int j = 0; j < 500; j++){
for (int i = 0; i < 16; i++){
// Perform an operation and store in the vector 'a[i]'
}
for (int i = 0; i < 16; i++){
// Add 'a[i]' to 'b' coefficient wise
}
}
我在每个for循环中使用OpenMp,在每个内部循环之前添加'#pragma omp parallel for'。我的所有处理器都在使用中,但我的运行时间只会显着增加。有没有人对如何减少这个循环的运行时有任何建议?先感谢您。
答案 0 :(得分:5)
omp为您的程序创建线程,无论您插入pragma标记,因此它为内部标记创建线程,但问题是创建了16个线程,每个线程执行1次操作,然后使用您的方法销毁所有线程。创建和销毁线程需要花费大量时间,因此您使用的方法会增加整个过程的时间,尽管它使用全部16个核心。你没有必要创建内部fors,只需在你的8000循环之前放置#pragma omp parallel for
标签就可以在踏板之间分隔值,所以你创建第二个循环所做的就是omp的工作。那样omp只创建一次线程,然后处理500个数字,然后使用每个线程并在此之后结束所有线程(使用499个线程创建和销毁)
答案 1 :(得分:3)
实际上,我将把这些评论作为答案。
为简单的操作分叉线程只会增加开销。
首先,确保您的编译器使用向量指令来实现循环。 (如果它不知道如何做到这一点,你可能必须自己编写矢量指令代码;尝试搜索“SSE instrinsics”。但是对于这种简单的向量添加,自动矢量化应该是可能的。)
假设您的编译器是一个相当现代的GCC,请使用以下命令调用它:
gcc -O3 -march=native ...
添加-ftree-vectorizer-verbose=2
以确定它是否为您的循环自动矢量化以及原因。
如果您已经在使用向量指令,则可能会使内存带宽饱和。现代CPU内核非常快......如果是这样,您需要在更高级别重构以在循环的每次迭代中获得更多操作,找到在适合L1缓存的块上执行大量操作的方法。
答案 2 :(得分:0)
Does anyone have any suggestions on how I can decrease the runtime of this loop?
for (int j = 0; j < 500; j++){ // outer loop
for (int i = 0; i < 16; i++){ // inner loop
始终尝试使外循环迭代小于内循环。这样可以多次避免内循环初始化。在上面的代码中,内循环i = 0;
被初始化500
次。现在,
for (int i = 0; j < 16; i++){ // outer loop
for (int j = 0; j < 500; j++){ // inner loop
现在,内循环j = 0;
只被初始化了16次!
如果它产生任何影响,请尝试相应地修改代码。