我一直在编写一个我在Macbook Pro上首次编写的OpenCL程序,因为我的桌面计算机更强大,我想移植代码并查看是否有任何改进。
运行相同的代码:
Mac:0.055452s
Win7:0.359s
两台计算机的规格如下: Mac:2.6GHz Intel Core i5,8GB 1600MHz DDR3,Intel Iris 1536MB
PC:3.3GHz Intel Core i5-2500k,8GB 1600MHz DDR3,AMD Radeon HD 6900系列
现在您可以看到我的Mac上运行的代码比我的台式PC快了近10倍。
我使用
计时代码#include<ctime>
clock_t begin = clock();
....// Entire main file
float timeTaken = (float)(clock() - begin) / CLOCKS_PER_SEC;
cout << "Time taken: " << timeTaken << endl;
如果我没弄错的话,PC和GPU上的CPU和GPU都会更强大。我可以使用这台台式电脑在Ultra设置上运行Battlefield 3。
唯一的区别可能是PC上的Visual Studio与另一个编译器编译?我在我的mac上使用了g ++,不确定Visual Studio使用了什么。
这些结果对我没有意义。你们有什么感想?如果你想查看代码,我可以发布github链接
编辑:以下github链接显示代码https://github.com/Batkow/OpenCL/tree/master/OpenCL。 PSO_V2使用教程中使用的编码类型:https://www.fixstars.com/en/opencl/book/OpenCLProgrammingBook/introduction-to-parallelization/
PSO使用此github存储库中的自定义标头简化了编码:https://github.com/HandsOnOpenCL/Exercises-Solutions ..
我使用NVidia Geforce 950M在我的朋友新款i7笔记本电脑上运行了代码,代码执行速度甚至比在我的台式机上还要慢。
我确实意识到代码没有经过优化,因此我对愚蠢的东西提出任何提示,请打电话给它。例如,在三个不同的内核函数中有一个while循环是一种愚蠢的权利吗?我正在努力在内核中实现所有内容并在其中循环,这应该可以提高性能吗?
更新:再次在家中的Windows上运行OpenCL / PSO代码。在while循环之前和之后对代码进行定时可以使WINDOWS的性能更快!
clock_t Win7 = 0.027,Mac = 0.036。使用带有Util :: Timer类Win7的外部.hpp运行:0.026秒,而Mac为0.085秒。
从主文件的开始到while循环(所有初始化)之前的时间,然后使用clock_t和Util :: Timer,Mac的得分比Windows几乎高10倍。所以瓶颈似乎是在设备的初始化?
答案 0 :(得分:1)
可能是几十件事 - CL内核的关键是什么,以及它在不同类型的GPU上的效果如何。或者使用什么编译器
但是,我认为问题在于你如何衡量时间。 Windows上的clock()
测量“wallclock-time”(换句话说“经过时间”),在OSX(以及所有其他理智的操作系统)上,它会报告您的进程的CPU时间。如果OSX在图形处理器上运行[或在单独的进程中],它将不计入CPU时间,其中Windows测量总时间。
在Windows上使用适当的CPU时间测量来测量CPU时间(例如,使用GetProcessTimes
)。或者使用c ++ std::chrono
来测量两个地方的挂钟时间。
答案 1 :(得分:1)
也许你测量流逝时间的方式存在问题,例如我在不同操作系统的项目中采用了三种不同的方式:
#include <cstdio>
#include <iostream>
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#elif defined(__linux__)
#include <time.h>
#elif defined(__APPLE__)
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <stddef.h>
#endif
#if defined(_WIN32) || defined(_WIN64)
LARGE_INTEGER frequency; // ticks per second
LARGE_INTEGER t0, t1, t2; // ticks
LARGE_INTEGER t3, t4;
#elif defined(__linux__)
timespec t0, t1, t2;
timespec t3, t4;
double us;
#elif defined(__APPLE__)
unsigned long t0, t1, t2;
#endif
double elapsedTime;
void refreshTime() {
#if defined(_WIN32) || defined(_WIN64)
QueryPerformanceFrequency(&frequency); // get ticks per second
QueryPerformanceCounter(&t1); // start timer
t0 = t1;
#elif defined(__linux__)
clock_gettime(CLOCK_MONOTONIC_RAW, &t1);
t0 = t1;
#elif defined(__APPLE__)
t1 = mach_absolute_time();
t0 = t1;
#endif
}
void watch_report(const char *str) {
#if defined(_WIN32) || defined(_WIN64)
QueryPerformanceCounter(&t2);
printf(str, (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart);
t1 = t2;
elapsedTime = (t2.QuadPart - t0.QuadPart) * 1000.0 / frequency.QuadPart;
#elif defined(__linux__)
clock_gettime(CLOCK_MONOTONIC_RAW, &t2);
time_t sec = t2.tv_sec - t1.tv_sec;
long nsec;
if (t2.tv_nsec >= t1.tv_nsec) {
nsec = t2.tv_nsec - t1.tv_nsec;
} else {
nsec = 1000000000 - (t1.tv_nsec - t2.tv_nsec);
sec -= 1;
}
printf(str, (float)sec * 1000.f + (float)nsec / 1000000.f);
t1 = t2;
elapsedTime = (float)(t2.tv_sec - t0.tv_sec) * 1000.f +
(float)(t2.tv_nsec - t0.tv_nsec) / 1000000.f;
#elif defined(__APPLE__)
uint64_t elapsedNano;
static mach_timebase_info_data_t sTimebaseInfo;
if (sTimebaseInfo.denom == 0) {
(void)mach_timebase_info(&sTimebaseInfo);
}
t2 = mach_absolute_time();
elapsedNano = (t2 - t1) * sTimebaseInfo.numer / sTimebaseInfo.denom;
printf(str, (float)elapsedNano / 1000000.f);
t1 = t2;
elapsedNano = (t2 - t0) * sTimebaseInfo.numer / sTimebaseInfo.denom;
elapsedTime = (float)elapsedNano / 1000000.f;
#endif
}
/*This Function will work till you press q*/
void someFunction() {
while (1) {
char ch = std::cin.get();
if (ch == 'q')
break;
}
}
int main() {
refreshTime();
someFunction();
watch_report("some function was working: \t%9.3f ms\n");
}
答案 2 :(得分:1)
因为clock()函数只计算CPU时钟周期。您的主机代码可能正在调用内核然后进入休眠状态。即使内核正在执行,这个休眠时间也不会被时钟函数计算。所以这意味着时钟函数只考虑主机代码的执行时间而不考虑openCL内核。您需要使用一个计算挂钟时间而不是CPU时钟周期的函数。
答案 3 :(得分:0)
我认为答案隐藏在CPU的几代人中。在你的电脑上它是Sandy Bridge(第二代)和Mac - Haswell(第四代)。这是两代人的差异。
OpenCL是在这几代英特尔处理器(Haswell中过多的硬件支持)中显着发展的事情之一。
只是为了得到证据 - 找一个配有Haswell CPU的桌面的朋友并运行你的测试。桌面Haswell处理器应该击败你的Mac(当然,如果其他硬件规格和整体系统负载匹配)。
答案 4 :(得分:0)
您已发布计时功能,但未发布OpenCL代码。什么都被定时?一个重要因素可能是内核编译时间(clCreateProgramFromSource和clBuildProgram)。您的PC可能正在使用缓存的内核而Mac则不是。衡量OpenCL内核执行时间的正确方法是使用OpenCL事件。
答案 5 :(得分:-1)
您可能获得该结果的另一个可能原因 - 也许您的程序编译为OpenCL ver.2.0。
在Windows上,您的GPU是从2010年开始的,它只支持OpenCL 1.2。
在OSX上,您的Intel GPU支持OpenCL 2.0。