├── .gitignore
├── CHANGELOG.md
├── ImageMagick.tgz
├── LICENSE
├── README.md
├── fftw
├── build.sh
├── fftw3.h
├── fftwtest.cpp
├── libfftw3.a
├── libfftw3_omp.a
└── libfftw3_threads.a
├── fftwtest
├── gfxCardStatus.tgz
├── macoh.conf
├── macoh.sh
├── make-release.sh
└── mprime.tgz
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | *~
3 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 |
4 | - 1.5.5, 2020-08-06 - Updated intel power gadget url and fetch
5 | - 1.5.4, 2016-04-27 - Updated urls for the BBB movie and the newest Intel Power Gadget (Core M compatible)
6 | - 1.5.3, 2015-08-14 - Fixed dependencies for FFT test
7 | - 1.5.2, 2015-03-11 - Fixed graph missing labels (tex problem)
8 | - 1.5.1, 2015-03-10 - Fixed FFT binary and number of default threads (cores - 1)
9 | - 1.5.0, 2015-03-10 - Plots power draw, indicate stats, detects Tmax and TDP overruns
10 | - 1.4.0, 2015-03-09 - Added my own FFT test (emulates humane CPU stress, should not throttle)
11 | - 1.3.4-beta, 2015-03-08 - Fixed Handbrake URL
12 | - 1.3.1-beta, 2014-05-26 - User defined command timeout fix
13 | - 1.3.0-beta, 2014-05-13 - Compiled Prime95 for command line (mprime), Prime95 can be started automatically, added Prime95 menu options, separate GpuTest and Prime95 durations in menu, cleaner menu, some bug fixes
14 | - 1.2.3-beta, 2014-05-11 - More compact menu
15 | - 1.2.2-beta, 2014-05-11 - Safer CPU priority code; fixed bug in perf stats between multiple runs
16 | - 1.2.1-beta, 2014-05-11 - CPU priority of HandBrake and GpuTest can now be changed (menu, conf); more bug fixes.
17 | - 1.2.0-beta, 2014-05-09 - GpuTest stats on graphs, cleaner code, lots of bug fixes
18 | - 1.1.2-beta, 2014-05-08 - Added GPU switching to command line.
19 | - 1.1.1-beta, 2014-05-07 - Bug fixing release.
20 | - 1.1.0-beta, 2014-05-06 - Added GpuTest, Prime95, gfxCardStatus, longer x264 test, more command line options.
21 | - 1.0.1-alpha, 2014-05-03 - Added command line options to bypass menu
22 | - 1.0.0-alpha, 2014-05-02 - First version
23 |
--------------------------------------------------------------------------------
/ImageMagick.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/ImageMagick.tgz
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MacOH
2 | =====
3 |
4 | Small tool for Mac OS X runs CPU and GPU stress tests, monitoring CPU frequency, temperature and power draw which are plotted versus time. The purpose is to evaluate CPU throttling and/or overheating (not performance).
5 |
6 | Output examples: [x264](http://www.damtp.cam.ac.uk/research/afha/people/bogdan/macoh/x264.png) (no throttling), [Prime95](http://www.damtp.cam.ac.uk/research/afha/people/bogdan/macoh/prime95.png) (heavy throttling), [3D-Intel 5100](http://www.damtp.cam.ac.uk/research/afha/people/bogdan/macoh/gputest-irispro.png) (throttling), [3D-Nvidia 750M](http://www.damtp.cam.ac.uk/research/afha/people/bogdan/macoh/gputest-gt750m.png) (no throttling).
7 |
8 | - Can do FFTs, x264 encodes, Prime95, GpuTest or a custom command/script of your choice
9 | - Monitors and logs CPU temperature and frequency during the test
10 | - Plots a graph of CPU temperature and frequency vs. time
11 | - Grabs free and open source tools as needed: [Intel Power Gadget](https://software.intel.com/en-us/articles/intel-power-gadget-20) (measuring and logging), [HandBrake CLI](http://handbrake.fr) (x264 transcoding), [Prime95](http://mersenne.org) (CPU stress), [GpuTest](http://www.geeks3d.com/gputest/) (GPU stress), [gfxCardStatus](http://gfx.io) (GPU switching), [Ggraphics Layout Engine](http://glx.sourceforge.net) (graph plotting), [ImageMagick](http://www.imagemagick.org) (better image processing than sips)
12 | - Grabs the free movie [Big Buck Bunny](http://www.bigbuckbunny.org) in 1080p (692 MB) as needed
13 |
14 | I recommend the FFT test with as many threads as physical cores (this is the default). This is more stressful than most common operations one typically does, but less stressful than the x264 test or Prime95 test. If the FFT test with half the threads is throttling then you have a real problem (2 threads for a quad core CPU). Expect Prime95 to cause heavy throttling on laptops. The x264 test is in between but (on my rMBP at least) it still causes higher power draw than the TDP limit which can trigger throttling. The 3D GpuTest, when run on integrated GPU, can also cause CPU throttling.
15 |
16 | Feedback
17 | --------
18 |
19 | The [dedicated thread on MacRumors forums](http://forums.macrumors.com/showthread.php?t=1731178) started containing results and discussions. Your contribution there would be very welcome. If it doesn't work for you, or if you find bugs, have suggestions, questions or comments then [drop a line on Github](https://github.com/qnxor/macoh/issues) or just [contact](http://www.damtp.cam.ac.uk/user/abr28) me.
20 |
21 | **Disclaimer:** As per the usual nitty gritty, I cannot be held responsible if your spouse leaves you after running this tool, or worse: if your Mac gets damaged. Most likely you'll be just fine though.
22 |
23 | Usage
24 | -----
25 |
26 | 1. [Donwload](https://github.com/qnxor/macoh/releases) the latest .zip release and extract it somewhere
27 | 1. Open Terminal and do `bash macoh.sh`
28 | 1. Choose a command in the (old school) menu
29 |
30 | #### Config file
31 |
32 | There is a `macoh.conf` configuration file which you can edit it to set various options (defaults). It is sourced by Bash in the main script so make sure you use valid Bash syntax.
33 |
34 | #### Command line alternative
35 |
36 | `bash macoh.sh [-OPTION VALUE [-OPTION VALUE ...]]`
37 |
38 | Where -OPTION VALUE can be:
39 |
40 | - `-do` - launch a test, one of: *x264*, *x264-long*, *gputest*, *prime95*
41 | - `-get` - fetch one of: *ipg*, *gle*, *gfx*, *imagick*, *video*, *handbrake*, *gputest*, *prime95*. These are downloaded as necessary upon launching of a test but can be invoked separately. The script will prompt if it detects already downloaded/installed items. Downloads are placed in $HOME/macoh/tmp and installations in $HOME/macoh/bin.
42 | - `-cmd` - A user defined command to execute and monitor. This must be the last option in the command line, everything after it is considered part of the user command. You can use this to launch your own stress test to be monitored and have the temp and freq vs time plotted. The command must not terminate immediately (e.g. do not use ''open MyBenchmark.app''). Also take note of the duration value (`-t`) below. The -cmd option needs more thorough testing, please report bugs.
43 | - `-t,-time` - duration of Prime95, GpuTest and user defined command in seconds, use 0 to run indefinitely (default is 600 for GpuTest and 300 for the rest, see macoh.conf). Prime95 and the user defined command are assumed to run indefintely by default, so this option is used to stop them, unless they exit or if you abort them early.
44 | - `-w,-wait` - waiting time before the test, to get idle temperature (default is 15 seconds, see macoh.conf)
45 | - `-g,-gputest` - change the GpuTest type to one of: *fur*, *tess_x8*, *tess_x16*, *tess_x32*, *tess_x64*, *gi*,*pixmark_piano*, *pixmark_volplosion*, *plot3d*, *triangle* (default is *tess_x64*, see macoh.conf)
46 | - `-r,-res` - change the resolution of GpuTest (default is 1280x720, unless altered in macoh.conf)
47 | - `-m,-msaa` - change the MSAA level of GpuTest to 0 (disabled), 2, 4, or 8 (default is 2, see macoh.conf).
48 | - `-s,-gpuswitch` - force the GPU to either of: **integrated**, **discrete** or **dynamic**. You can also use **1**, **2** or **3** as synonyms. This setting only affects laptops with dual GPU (e.g. Intel Iris Pro and Nvidia). Note that this persists even after the script exits. The default setting is **dynamic** (unless you altrered it priorly) which means that the discrete GPU is in 3D. If you do not specify `-do` or `-cmd` then the script will exit after swicthing GPU (useful for scripting).
49 |
50 | #### Command line examples
51 |
52 | `macoh.sh -do x264 -wait 30` will launch the x264 transcode test with 30 seconds wait time beforehand and afterwards, downloading and installing the tools and the video as needed (skipping those already done), and generating `$HOME/macoh/${DATE}-x264.png`, `$HOME/macoh/logs/${DATE}-ipg.csv` and `$HOME/macoh/logs/${DATE}-hb.log`.
53 |
54 | `macoh.sh -do gputest -wait 10 -res 1600x900 -msaa 0 -gputest tess_x64` will launch the TessMark test from GpuTest in a 1600x900 window with MSAA disabled and a wait time beforehand and afterwards of 10 seconds.
55 |
56 | `macoh.sh -time 180 -cmd /Applications/Heaven.app/Contents/MacOS/heaven` will launch the Unigine Heaven 3D benchmark (installed separately) and will kill it after 180 seconds unless you quit it by then. You must start the Heaven benchmark manually once its app GUI opens since the script has no control over it.
57 |
58 | #### Uninstall, Folders, etc.
59 |
60 | To unistall, do: *(1)* /Applications > Intel Power Gadget > Uninstaller and *(2)* `rm -rf ~/macoh/*/*`. The latter wipes everything except generated graphs and downloaded video (note the `/*/*`).
61 |
62 | The script writes only to your home dir in `$HOME/macoh`. The only exception is Intel Power Gadget which is installed in /Applications.
63 |
64 | You can make it executable with `chmod u+x macoh.sh` and then do `./macoh.sh`.
65 |
66 | Known issues
67 | ------------
68 |
69 | gfxCardStatus has [a bug](https://github.com/codykrieger/gfxCardStatus/issues/103), it needs somes convincing to switch the GPU. The `macoh` script makes two attempts and normally gets it. Just in case it doesn't, you may need to insist or open the app normally (via Finder/Spotlight) and switch the GPU there.
70 |
71 | Todo
72 | ----
73 |
74 | - [ ] Fan speed monitoring +graph (any free tool?) [#2](//github.com/qnxor/macoh/issues/2)
75 | - [ ] GPU freq and temp monitoring +graph (any free tool?) [#6](//github.com/qnxor/macoh/issues/6)
76 | - [x] Add GPU testing
77 | - [x] Add Prime95
78 | - [x] Stats, Tjunction and TDP detection, etc [#3](//github.com/qnxor/macoh/issues/3)
79 | - [x] GpuTest results
80 | - [ ] Uninstall/clean option [#4](//github.com/qnxor/macoh/issues/4)
81 | - [ ] Auto-upload results and graph somewhere (with prompt)?
82 | - [ ] Cross-platform version?
83 |
84 | Credits
85 | -------
86 |
87 | A local version of Intel Power Gadget is stored in the project for consistency. All copyright is of Intel. Binary versions of the open source applications ImageMagick, gfxCardStatus and Prime95 are also stored in the project. Using the [FFTW library](http://fftw.org) for the FFT computations. The sources of gfxCardStatus and Prime95 were modified and compiled to fit the current project.
88 |
--------------------------------------------------------------------------------
/fftw/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Compile FFTW3 library MACOSX_X64 + GCC-4.9 (from Macports, port install gcc49):
4 | #
5 | # ./configure --enable-sse2 --enable-avx --enable-threads --enable-openmp
6 | # ln -s /usr/bin/clang /opt/local/bin/clang
7 | # make -j4 CFLAGS+=-Wa,-q
8 | #
9 | # You need the native clang assembler or else you can't compile the AVX
10 | # extensions ("no such instruction: ..." errors), so symlink /usr/bin/clang
11 | # into /opt/local/bin/ and then pass -Wa,-q to make's CFLAGS.
12 |
13 | cwd=`dirname $0`
14 | libgomp=/opt/local/lib/gcc49/libgomp.a
15 |
16 | # g++-mp-4.9 -O3 -fopenmp -L`dirname $0` -lgomp -lfftw3_omp -lfftw3 -o fftwtest `dirname $0`/fftwtest.cpp
17 | g++-mp-4.9 -O3 -static-libgcc -static-libstdc++ "$cwd/fftwtest.cpp" -o fftwtest \
18 | "$libgomp" "$cwd/libfftw3_omp.a" "$cwd/libfftw3.a"
19 |
20 | # upx pack it?
21 | # download upx for mac here: http://www.idrix.fr/Root/content/category/7/26/49/
22 | #upx -9 --lzma fftwtest
23 |
--------------------------------------------------------------------------------
/fftw/fftw3.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2003, 2007-14 Matteo Frigo
3 | * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
4 | *
5 | * The following statement of license applies *only* to this header file,
6 | * and *not* to the other files distributed with FFTW or derived therefrom:
7 | *
8 | * Redistribution and use in source and binary forms, with or without
9 | * modification, are permitted provided that the following conditions
10 | * are met:
11 | *
12 | * 1. Redistributions of source code must retain the above copyright
13 | * notice, this list of conditions and the following disclaimer.
14 | *
15 | * 2. Redistributions in binary form must reproduce the above copyright
16 | * notice, this list of conditions and the following disclaimer in the
17 | * documentation and/or other materials provided with the distribution.
18 | *
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
20 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 | */
31 |
32 | /***************************** NOTE TO USERS *********************************
33 | *
34 | * THIS IS A HEADER FILE, NOT A MANUAL
35 | *
36 | * If you want to know how to use FFTW, please read the manual,
37 | * online at http://www.fftw.org/doc/ and also included with FFTW.
38 | * For a quick start, see the manual's tutorial section.
39 | *
40 | * (Reading header files to learn how to use a library is a habit
41 | * stemming from code lacking a proper manual. Arguably, it's a
42 | * *bad* habit in most cases, because header files can contain
43 | * interfaces that are not part of the public, stable API.)
44 | *
45 | ****************************************************************************/
46 |
47 | #ifndef FFTW3_H
48 | #define FFTW3_H
49 |
50 | #include
51 |
52 | #ifdef __cplusplus
53 | extern "C"
54 | {
55 | #endif /* __cplusplus */
56 |
57 | /* If is included, use the C99 complex type. Otherwise
58 | define a type bit-compatible with C99 complex */
59 | #if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
60 | # define FFTW_DEFINE_COMPLEX(R, C) typedef R _Complex C
61 | #else
62 | # define FFTW_DEFINE_COMPLEX(R, C) typedef R C[2]
63 | #endif
64 |
65 | #define FFTW_CONCAT(prefix, name) prefix ## name
66 | #define FFTW_MANGLE_DOUBLE(name) FFTW_CONCAT(fftw_, name)
67 | #define FFTW_MANGLE_FLOAT(name) FFTW_CONCAT(fftwf_, name)
68 | #define FFTW_MANGLE_LONG_DOUBLE(name) FFTW_CONCAT(fftwl_, name)
69 | #define FFTW_MANGLE_QUAD(name) FFTW_CONCAT(fftwq_, name)
70 |
71 | /* IMPORTANT: for Windows compilers, you should add a line
72 | #define FFTW_DLL
73 | here and in kernel/ifftw.h if you are compiling/using FFTW as a
74 | DLL, in order to do the proper importing/exporting, or
75 | alternatively compile with -DFFTW_DLL or the equivalent
76 | command-line flag. This is not necessary under MinGW/Cygwin, where
77 | libtool does the imports/exports automatically. */
78 | #if defined(FFTW_DLL) && (defined(_WIN32) || defined(__WIN32__))
79 | /* annoying Windows syntax for shared-library declarations */
80 | # if defined(COMPILING_FFTW) /* defined in api.h when compiling FFTW */
81 | # define FFTW_EXTERN extern __declspec(dllexport)
82 | # else /* user is calling FFTW; import symbol */
83 | # define FFTW_EXTERN extern __declspec(dllimport)
84 | # endif
85 | #else
86 | # define FFTW_EXTERN extern
87 | #endif
88 |
89 | enum fftw_r2r_kind_do_not_use_me {
90 | FFTW_R2HC=0, FFTW_HC2R=1, FFTW_DHT=2,
91 | FFTW_REDFT00=3, FFTW_REDFT01=4, FFTW_REDFT10=5, FFTW_REDFT11=6,
92 | FFTW_RODFT00=7, FFTW_RODFT01=8, FFTW_RODFT10=9, FFTW_RODFT11=10
93 | };
94 |
95 | struct fftw_iodim_do_not_use_me {
96 | int n; /* dimension size */
97 | int is; /* input stride */
98 | int os; /* output stride */
99 | };
100 |
101 | #include /* for ptrdiff_t */
102 | struct fftw_iodim64_do_not_use_me {
103 | ptrdiff_t n; /* dimension size */
104 | ptrdiff_t is; /* input stride */
105 | ptrdiff_t os; /* output stride */
106 | };
107 |
108 | typedef void (*fftw_write_char_func_do_not_use_me)(char c, void *);
109 | typedef int (*fftw_read_char_func_do_not_use_me)(void *);
110 |
111 | /*
112 | huge second-order macro that defines prototypes for all API
113 | functions. We expand this macro for each supported precision
114 |
115 | X: name-mangling macro
116 | R: real data type
117 | C: complex data type
118 | */
119 |
120 | #define FFTW_DEFINE_API(X, R, C) \
121 | \
122 | FFTW_DEFINE_COMPLEX(R, C); \
123 | \
124 | typedef struct X(plan_s) *X(plan); \
125 | \
126 | typedef struct fftw_iodim_do_not_use_me X(iodim); \
127 | typedef struct fftw_iodim64_do_not_use_me X(iodim64); \
128 | \
129 | typedef enum fftw_r2r_kind_do_not_use_me X(r2r_kind); \
130 | \
131 | typedef fftw_write_char_func_do_not_use_me X(write_char_func); \
132 | typedef fftw_read_char_func_do_not_use_me X(read_char_func); \
133 | \
134 | FFTW_EXTERN void X(execute)(const X(plan) p); \
135 | \
136 | FFTW_EXTERN X(plan) X(plan_dft)(int rank, const int *n, \
137 | C *in, C *out, int sign, unsigned flags); \
138 | \
139 | FFTW_EXTERN X(plan) X(plan_dft_1d)(int n, C *in, C *out, int sign, \
140 | unsigned flags); \
141 | FFTW_EXTERN X(plan) X(plan_dft_2d)(int n0, int n1, \
142 | C *in, C *out, int sign, unsigned flags); \
143 | FFTW_EXTERN X(plan) X(plan_dft_3d)(int n0, int n1, int n2, \
144 | C *in, C *out, int sign, unsigned flags); \
145 | \
146 | FFTW_EXTERN X(plan) X(plan_many_dft)(int rank, const int *n, \
147 | int howmany, \
148 | C *in, const int *inembed, \
149 | int istride, int idist, \
150 | C *out, const int *onembed, \
151 | int ostride, int odist, \
152 | int sign, unsigned flags); \
153 | \
154 | FFTW_EXTERN X(plan) X(plan_guru_dft)(int rank, const X(iodim) *dims, \
155 | int howmany_rank, \
156 | const X(iodim) *howmany_dims, \
157 | C *in, C *out, \
158 | int sign, unsigned flags); \
159 | FFTW_EXTERN X(plan) X(plan_guru_split_dft)(int rank, const X(iodim) *dims, \
160 | int howmany_rank, \
161 | const X(iodim) *howmany_dims, \
162 | R *ri, R *ii, R *ro, R *io, \
163 | unsigned flags); \
164 | \
165 | FFTW_EXTERN X(plan) X(plan_guru64_dft)(int rank, \
166 | const X(iodim64) *dims, \
167 | int howmany_rank, \
168 | const X(iodim64) *howmany_dims, \
169 | C *in, C *out, \
170 | int sign, unsigned flags); \
171 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft)(int rank, \
172 | const X(iodim64) *dims, \
173 | int howmany_rank, \
174 | const X(iodim64) *howmany_dims, \
175 | R *ri, R *ii, R *ro, R *io, \
176 | unsigned flags); \
177 | \
178 | FFTW_EXTERN void X(execute_dft)(const X(plan) p, C *in, C *out); \
179 | FFTW_EXTERN void X(execute_split_dft)(const X(plan) p, R *ri, R *ii, \
180 | R *ro, R *io); \
181 | \
182 | FFTW_EXTERN X(plan) X(plan_many_dft_r2c)(int rank, const int *n, \
183 | int howmany, \
184 | R *in, const int *inembed, \
185 | int istride, int idist, \
186 | C *out, const int *onembed, \
187 | int ostride, int odist, \
188 | unsigned flags); \
189 | \
190 | FFTW_EXTERN X(plan) X(plan_dft_r2c)(int rank, const int *n, \
191 | R *in, C *out, unsigned flags); \
192 | \
193 | FFTW_EXTERN X(plan) X(plan_dft_r2c_1d)(int n,R *in,C *out,unsigned flags); \
194 | FFTW_EXTERN X(plan) X(plan_dft_r2c_2d)(int n0, int n1, \
195 | R *in, C *out, unsigned flags); \
196 | FFTW_EXTERN X(plan) X(plan_dft_r2c_3d)(int n0, int n1, \
197 | int n2, \
198 | R *in, C *out, unsigned flags); \
199 | \
200 | \
201 | FFTW_EXTERN X(plan) X(plan_many_dft_c2r)(int rank, const int *n, \
202 | int howmany, \
203 | C *in, const int *inembed, \
204 | int istride, int idist, \
205 | R *out, const int *onembed, \
206 | int ostride, int odist, \
207 | unsigned flags); \
208 | \
209 | FFTW_EXTERN X(plan) X(plan_dft_c2r)(int rank, const int *n, \
210 | C *in, R *out, unsigned flags); \
211 | \
212 | FFTW_EXTERN X(plan) X(plan_dft_c2r_1d)(int n,C *in,R *out,unsigned flags); \
213 | FFTW_EXTERN X(plan) X(plan_dft_c2r_2d)(int n0, int n1, \
214 | C *in, R *out, unsigned flags); \
215 | FFTW_EXTERN X(plan) X(plan_dft_c2r_3d)(int n0, int n1, \
216 | int n2, \
217 | C *in, R *out, unsigned flags); \
218 | \
219 | FFTW_EXTERN X(plan) X(plan_guru_dft_r2c)(int rank, const X(iodim) *dims, \
220 | int howmany_rank, \
221 | const X(iodim) *howmany_dims, \
222 | R *in, C *out, \
223 | unsigned flags); \
224 | FFTW_EXTERN X(plan) X(plan_guru_dft_c2r)(int rank, const X(iodim) *dims, \
225 | int howmany_rank, \
226 | const X(iodim) *howmany_dims, \
227 | C *in, R *out, \
228 | unsigned flags); \
229 | \
230 | FFTW_EXTERN X(plan) X(plan_guru_split_dft_r2c)( \
231 | int rank, const X(iodim) *dims, \
232 | int howmany_rank, \
233 | const X(iodim) *howmany_dims, \
234 | R *in, R *ro, R *io, \
235 | unsigned flags); \
236 | FFTW_EXTERN X(plan) X(plan_guru_split_dft_c2r)( \
237 | int rank, const X(iodim) *dims, \
238 | int howmany_rank, \
239 | const X(iodim) *howmany_dims, \
240 | R *ri, R *ii, R *out, \
241 | unsigned flags); \
242 | \
243 | FFTW_EXTERN X(plan) X(plan_guru64_dft_r2c)(int rank, \
244 | const X(iodim64) *dims, \
245 | int howmany_rank, \
246 | const X(iodim64) *howmany_dims, \
247 | R *in, C *out, \
248 | unsigned flags); \
249 | FFTW_EXTERN X(plan) X(plan_guru64_dft_c2r)(int rank, \
250 | const X(iodim64) *dims, \
251 | int howmany_rank, \
252 | const X(iodim64) *howmany_dims, \
253 | C *in, R *out, \
254 | unsigned flags); \
255 | \
256 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft_r2c)( \
257 | int rank, const X(iodim64) *dims, \
258 | int howmany_rank, \
259 | const X(iodim64) *howmany_dims, \
260 | R *in, R *ro, R *io, \
261 | unsigned flags); \
262 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft_c2r)( \
263 | int rank, const X(iodim64) *dims, \
264 | int howmany_rank, \
265 | const X(iodim64) *howmany_dims, \
266 | R *ri, R *ii, R *out, \
267 | unsigned flags); \
268 | \
269 | FFTW_EXTERN void X(execute_dft_r2c)(const X(plan) p, R *in, C *out); \
270 | FFTW_EXTERN void X(execute_dft_c2r)(const X(plan) p, C *in, R *out); \
271 | \
272 | FFTW_EXTERN void X(execute_split_dft_r2c)(const X(plan) p, \
273 | R *in, R *ro, R *io); \
274 | FFTW_EXTERN void X(execute_split_dft_c2r)(const X(plan) p, \
275 | R *ri, R *ii, R *out); \
276 | \
277 | FFTW_EXTERN X(plan) X(plan_many_r2r)(int rank, const int *n, \
278 | int howmany, \
279 | R *in, const int *inembed, \
280 | int istride, int idist, \
281 | R *out, const int *onembed, \
282 | int ostride, int odist, \
283 | const X(r2r_kind) *kind, unsigned flags); \
284 | \
285 | FFTW_EXTERN X(plan) X(plan_r2r)(int rank, const int *n, R *in, R *out, \
286 | const X(r2r_kind) *kind, unsigned flags); \
287 | \
288 | FFTW_EXTERN X(plan) X(plan_r2r_1d)(int n, R *in, R *out, \
289 | X(r2r_kind) kind, unsigned flags); \
290 | FFTW_EXTERN X(plan) X(plan_r2r_2d)(int n0, int n1, R *in, R *out, \
291 | X(r2r_kind) kind0, X(r2r_kind) kind1, \
292 | unsigned flags); \
293 | FFTW_EXTERN X(plan) X(plan_r2r_3d)(int n0, int n1, int n2, \
294 | R *in, R *out, X(r2r_kind) kind0, \
295 | X(r2r_kind) kind1, X(r2r_kind) kind2, \
296 | unsigned flags); \
297 | \
298 | FFTW_EXTERN X(plan) X(plan_guru_r2r)(int rank, const X(iodim) *dims, \
299 | int howmany_rank, \
300 | const X(iodim) *howmany_dims, \
301 | R *in, R *out, \
302 | const X(r2r_kind) *kind, unsigned flags); \
303 | \
304 | FFTW_EXTERN X(plan) X(plan_guru64_r2r)(int rank, const X(iodim64) *dims, \
305 | int howmany_rank, \
306 | const X(iodim64) *howmany_dims, \
307 | R *in, R *out, \
308 | const X(r2r_kind) *kind, unsigned flags); \
309 | \
310 | FFTW_EXTERN void X(execute_r2r)(const X(plan) p, R *in, R *out); \
311 | \
312 | FFTW_EXTERN void X(destroy_plan)(X(plan) p); \
313 | FFTW_EXTERN void X(forget_wisdom)(void); \
314 | FFTW_EXTERN void X(cleanup)(void); \
315 | \
316 | FFTW_EXTERN void X(set_timelimit)(double t); \
317 | \
318 | FFTW_EXTERN void X(plan_with_nthreads)(int nthreads); \
319 | FFTW_EXTERN int X(init_threads)(void); \
320 | FFTW_EXTERN void X(cleanup_threads)(void); \
321 | \
322 | FFTW_EXTERN int X(export_wisdom_to_filename)(const char *filename); \
323 | FFTW_EXTERN void X(export_wisdom_to_file)(FILE *output_file); \
324 | FFTW_EXTERN char *X(export_wisdom_to_string)(void); \
325 | FFTW_EXTERN void X(export_wisdom)(X(write_char_func) write_char, \
326 | void *data); \
327 | FFTW_EXTERN int X(import_system_wisdom)(void); \
328 | FFTW_EXTERN int X(import_wisdom_from_filename)(const char *filename); \
329 | FFTW_EXTERN int X(import_wisdom_from_file)(FILE *input_file); \
330 | FFTW_EXTERN int X(import_wisdom_from_string)(const char *input_string); \
331 | FFTW_EXTERN int X(import_wisdom)(X(read_char_func) read_char, void *data); \
332 | \
333 | FFTW_EXTERN void X(fprint_plan)(const X(plan) p, FILE *output_file); \
334 | FFTW_EXTERN void X(print_plan)(const X(plan) p); \
335 | FFTW_EXTERN char *X(sprint_plan)(const X(plan) p); \
336 | \
337 | FFTW_EXTERN void *X(malloc)(size_t n); \
338 | FFTW_EXTERN R *X(alloc_real)(size_t n); \
339 | FFTW_EXTERN C *X(alloc_complex)(size_t n); \
340 | FFTW_EXTERN void X(free)(void *p); \
341 | \
342 | FFTW_EXTERN void X(flops)(const X(plan) p, \
343 | double *add, double *mul, double *fmas); \
344 | FFTW_EXTERN double X(estimate_cost)(const X(plan) p); \
345 | FFTW_EXTERN double X(cost)(const X(plan) p); \
346 | \
347 | FFTW_EXTERN int X(alignment_of)(R *p); \
348 | FFTW_EXTERN const char X(version)[]; \
349 | FFTW_EXTERN const char X(cc)[]; \
350 | FFTW_EXTERN const char X(codelet_optim)[];
351 |
352 |
353 | /* end of FFTW_DEFINE_API macro */
354 |
355 | FFTW_DEFINE_API(FFTW_MANGLE_DOUBLE, double, fftw_complex)
356 | FFTW_DEFINE_API(FFTW_MANGLE_FLOAT, float, fftwf_complex)
357 | FFTW_DEFINE_API(FFTW_MANGLE_LONG_DOUBLE, long double, fftwl_complex)
358 |
359 | /* __float128 (quad precision) is a gcc extension on i386, x86_64, and ia64
360 | for gcc >= 4.6 (compiled in FFTW with --enable-quad-precision) */
361 | #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) \
362 | && !(defined(__ICC) || defined(__INTEL_COMPILER)) \
363 | && (defined(__i386__) || defined(__x86_64__) || defined(__ia64__))
364 | # if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I)
365 | /* note: __float128 is a typedef, which is not supported with the _Complex
366 | keyword in gcc, so instead we use this ugly __attribute__ version.
367 | However, we can't simply pass the __attribute__ version to
368 | FFTW_DEFINE_API because the __attribute__ confuses gcc in pointer
369 | types. Hence redefining FFTW_DEFINE_COMPLEX. Ugh. */
370 | # undef FFTW_DEFINE_COMPLEX
371 | # define FFTW_DEFINE_COMPLEX(R, C) typedef _Complex float __attribute__((mode(TC))) C
372 | # endif
373 | FFTW_DEFINE_API(FFTW_MANGLE_QUAD, __float128, fftwq_complex)
374 | #endif
375 |
376 | #define FFTW_FORWARD (-1)
377 | #define FFTW_BACKWARD (+1)
378 |
379 | #define FFTW_NO_TIMELIMIT (-1.0)
380 |
381 | /* documented flags */
382 | #define FFTW_MEASURE (0U)
383 | #define FFTW_DESTROY_INPUT (1U << 0)
384 | #define FFTW_UNALIGNED (1U << 1)
385 | #define FFTW_CONSERVE_MEMORY (1U << 2)
386 | #define FFTW_EXHAUSTIVE (1U << 3) /* NO_EXHAUSTIVE is default */
387 | #define FFTW_PRESERVE_INPUT (1U << 4) /* cancels FFTW_DESTROY_INPUT */
388 | #define FFTW_PATIENT (1U << 5) /* IMPATIENT is default */
389 | #define FFTW_ESTIMATE (1U << 6)
390 | #define FFTW_WISDOM_ONLY (1U << 21)
391 |
392 | /* undocumented beyond-guru flags */
393 | #define FFTW_ESTIMATE_PATIENT (1U << 7)
394 | #define FFTW_BELIEVE_PCOST (1U << 8)
395 | #define FFTW_NO_DFT_R2HC (1U << 9)
396 | #define FFTW_NO_NONTHREADED (1U << 10)
397 | #define FFTW_NO_BUFFERING (1U << 11)
398 | #define FFTW_NO_INDIRECT_OP (1U << 12)
399 | #define FFTW_ALLOW_LARGE_GENERIC (1U << 13) /* NO_LARGE_GENERIC is default */
400 | #define FFTW_NO_RANK_SPLITS (1U << 14)
401 | #define FFTW_NO_VRANK_SPLITS (1U << 15)
402 | #define FFTW_NO_VRECURSE (1U << 16)
403 | #define FFTW_NO_SIMD (1U << 17)
404 | #define FFTW_NO_SLOW (1U << 18)
405 | #define FFTW_NO_FIXED_RADIX_LARGE_N (1U << 19)
406 | #define FFTW_ALLOW_PRUNING (1U << 20)
407 |
408 | #ifdef __cplusplus
409 | } /* extern "C" */
410 | #endif /* __cplusplus */
411 |
412 | #endif /* FFTW3_H */
413 |
--------------------------------------------------------------------------------
/fftw/fftwtest.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * FFTW Test part of the MacOH project
3 | * https://github.com/qnxor/macoh
4 | *
5 | * Bogdan Roman, University of Cambridge, 2015
6 | * http://www.damtp.cam.ac.uk/research/afha/bogdan
7 | */
8 |
9 | #include
10 | #include
11 | #include "fftw3.h"
12 | #include
13 | #include
14 |
15 | void* moh_malloc(size_t n)
16 | {
17 | void* x = fftw_malloc(n);
18 | if (x)
19 | return x;
20 | else
21 | {
22 | fprintf(stderr, "Could not allocate memory. Decrease N and retry.\n");
23 | exit(3);
24 | }
25 | }
26 |
27 | void moh_fill (double* x, int n)
28 | {
29 | for (int i = 0; i < n*n; ++i)
30 | x[i] = rand() % n*n;
31 | }
32 |
33 | void moh_fill (fftw_complex* x, int n)
34 | {
35 | for (int i = 0; i < n*n; ++i)
36 | {
37 | x[i][0] = rand() % n*n;
38 | x[i][1] = rand() % n*n;
39 | }
40 | }
41 |
42 | int main(int argc, char **argv)
43 | {
44 | if (argc < 6 || atoi(argv[1]) < 2)
45 | {
46 | printf("Syntax: %s TIME THREADS N TYPE WISDOM\n\
47 | \n\
48 | TIME - run for continuously for this many seconds\n\
49 | THREADS - number of threads to use, 0 = all cores (x2 if HyperThreaded)\n\
50 | N - generate a random N-by-N input, N must be > 1\n\
51 | TYPE - 0=r2r, 1=r2c, 2=c2c\n\
52 | WISDOM - 0=ESTIMATE, 1=MEASURE, 2=PATIENT, 3=EXHAUSTIVE\n\
53 | \n\
54 | by Bogdan Roman, University of Cambridge, 2015\n\
55 | http://www.damtp.cam.ac.uk/research/afha/bogdan\n\
56 | Using FFTW3 (http://fftw.org), OpenMP (http://openmp.org)\n\
57 | ", argv[0]);
58 | exit(1);
59 | }
60 |
61 | double seconds = atof(argv[1]);
62 | int threads = atoi(argv[2]);
63 | int n = atoi(argv[3]);
64 | int type = atoi(argv[4]);
65 | int wisdom = atoi(argv[5]);
66 | int omp = threads != 1;
67 | time_t now, start = time(NULL);
68 | long count = 0;
69 |
70 | if (threads <= 0)
71 | threads = omp_get_max_threads();
72 |
73 | fprintf(stderr, "FFTW: size=%d-by-%d, threads=%d, type=%d, wisdom=%d. Planning ...\n",
74 | seconds, n, n, threads, type, wisdom);
75 |
76 | if (omp)
77 | {
78 | fftw_init_threads();
79 | fftw_plan_with_nthreads(threads);
80 | }
81 |
82 | switch (wisdom)
83 | {
84 | case 0: wisdom = FFTW_ESTIMATE; break;
85 | case 1: wisdom = FFTW_MEASURE; break;
86 | case 2: wisdom = FFTW_PATIENT; break;
87 | case 3: wisdom = FFTW_EXHAUSTIVE; break;
88 | default: printf("Unknown wisdom: %d\n", wisdom); exit(2);
89 | }
90 |
91 | //if (argc > 2)
92 | // fftw_import_wisdom_from_filename(argv[3]);
93 |
94 | fftw_plan p;
95 | void *x, *y;
96 |
97 | switch(type)
98 | {
99 | case 0:
100 | x = moh_malloc(n*n * sizeof(double));
101 | y = moh_malloc(n*n * sizeof(double));
102 | moh_fill((double*)x, n);
103 | p = fftw_plan_r2r_2d(n, n, (double*)x, (double*)y, FFTW_REDFT10, FFTW_REDFT10, wisdom);
104 | break;
105 | case 1:
106 | x = moh_malloc(n*n * sizeof(double));
107 | y = moh_malloc(n*n * sizeof(fftw_complex));
108 | moh_fill((double*)x, n);
109 | p = fftw_plan_dft_r2c_2d(n, n, (double*)x, (fftw_complex*)y, wisdom);
110 | break;
111 | case 2:
112 | x = moh_malloc(n*n * sizeof(fftw_complex));
113 | y = moh_malloc(n*n * sizeof(fftw_complex));
114 | moh_fill((fftw_complex*)x, n);
115 | p = fftw_plan_dft_2d(n, n, (fftw_complex*)x, (fftw_complex*)y, FFTW_FORWARD, wisdom);
116 | break;
117 | default:
118 | printf("Unknown type: %d\n", wisdom); exit(2);
119 | }
120 |
121 | fprintf(stderr, "FFTW: done planning in %.2f seconds. Looping for %.1f seconds ...\n",
122 | difftime(time(NULL),start), seconds);
123 |
124 | for (count = 0, start = time(NULL); difftime(time(NULL), start) < seconds; ++count)
125 | fftw_execute(p);
126 |
127 | printf("Done: %.2f ffts/sec\n", (double)count/difftime(time(NULL),start));
128 |
129 | //if (argc > 2)
130 | // fftw_export_wisdom_to_filename("fftw.wis");
131 |
132 | fftw_destroy_plan(p);
133 | if (omp)
134 | fftw_cleanup_threads();
135 | fftw_free(x);
136 | fftw_free(y);
137 | }
138 |
--------------------------------------------------------------------------------
/fftw/libfftw3.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/fftw/libfftw3.a
--------------------------------------------------------------------------------
/fftw/libfftw3_omp.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/fftw/libfftw3_omp.a
--------------------------------------------------------------------------------
/fftw/libfftw3_threads.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/fftw/libfftw3_threads.a
--------------------------------------------------------------------------------
/fftwtest:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/fftwtest
--------------------------------------------------------------------------------
/gfxCardStatus.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/gfxCardStatus.tgz
--------------------------------------------------------------------------------
/macoh.conf:
--------------------------------------------------------------------------------
1 | #### The working directory.
2 | # This will be used to download and place all files. Will be created if it
3 | # doesn't exist. Make surfe you have write permissions in the parent dir.
4 | home=~/macoh
5 |
6 | ### Wait time before and after the test
7 | # waitstart is used to capture idle temperature, don't set to 0.
8 | # waitend is useful to see how quickly it cools off.
9 | # Pertinent values for both: 15-30 sec.
10 | waitstart=15 # wait time before test (seconds)
11 | waitend=15 # wait time after test (seconds)
12 |
13 | ### Intel Power Gadget polling period (milliseconds)
14 | ipgpoll=500
15 |
16 | ### FFT options
17 | # Duration is in seconds
18 | fftsize=2048 # N, applies a 2D FFT on a random 2D N-by-N matrix
19 | fftduration=300 # duration (seconds)
20 | fftthreads=0 # -1 = nr of physical cores minus 1 (auto)
21 | # 0 = max threads (auto, 2xPhyCores if HyperThreaded)
22 | # n = use n > 0 threads
23 | ffttype=0
24 | fftwisdom=0
25 |
26 | ### GpuTest options
27 | # gputest can be: fur, tess_x8, tess_x16, tess_x32, tess_x64, gi,
28 | # pixmark_piano, pixmark_volplosion, plot3d, triangle.
29 | gputest=tess_x64 # see above
30 | gpumsaa=2 # 0,2,4,8 ... 0 disables MSAA
31 | gpuwidth=1280 # width (pixels)
32 | gpuheight=720 # height (pixels)
33 | gpuduration=600 # duration (seconds)
34 |
35 | ### Prime95 options
36 | # In-place FFTs are the most stressful. Larger FFTs (e.g. 128k or more)
37 | # are even more stressful.
38 | p95min=8 # Min FFT size (k)
39 | p95max=8 # Max FFT size (k)
40 | p95mem=0 # FFT memory (MB), 0 = in-place
41 | p95time=5 # time for each FFT (minutes)
42 | p95duration=300 # test duration (seconds)
43 |
44 | ### User command options
45 | # Max duration in seconds, 0=indefinte (if the user command stops by itself
46 | # then set this to either 0 or a sufficiently high value)
47 | usercmdduration=300
48 |
49 | ### Niceness (CPU priority) of FFT, HandBrake, GpuTest, Prime95.
50 | # An integer between -19 and 20. Negative values (less nice) means more CPU
51 | # priority, i.e. -19 means the highest priority (usually reserved for critical
52 | # OS processes). If you intend to run both HandBrake and GpuTest at the same
53 | # time then set both to the same nice level.
54 | # NOTE: You should *not* set this to more than 0 or else all other processes
55 | # which default to 0 will trump the stress tests which won't be able to
56 | # push the CPU as much, and result in misleading temp/freq results.
57 | # NOTE2: The Prime95 nice level is only for the master process. The child
58 | # processes are nice'd automatically.
59 | fftnice=-10
60 | hbnice=-10
61 | gpunice=-10
62 | p95nice=0
63 |
64 | ### Various
65 | # Output of HandBrake (transcoded movie). Set it to an actual file if you
66 | # want it saved (e.g. "$home/transcoded.mkv"). By default it goes into
67 | # /dev/null to avoid any disk I/O
68 | mkv=/dev/null
69 |
70 | # Quit main menu after running a test? 1=yes, 0=no
71 | menuquit=0
72 |
73 | ### URLs of the toold/content
74 | # HTTP redirects will be followed. You should NOT change these unless you
75 | # know what you're doing (useful for updates).
76 | #url_ipg="https://github.com/qnxor/macoh/raw/master/IntelPowerGadgetMac.zip"
77 | url_ipg="https://software.intel.com/file/501089/download"
78 | url_handbrake="http://download.handbrake.fr/releases/0.9.9/HandBrake-0.9.9-MacOSX.6_CLI_x86_64.dmg"
79 | url_gle="http://heanet.dl.sourceforge.net/project/glx/gle4%20(Current%20Active%20Version)/4.2.4c/gle-graphics-4.2.4c-exe-mac.dmg"
80 | url_video="http://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_1080p_h264.mov"
81 | # url_prime95="ftp://mersenne.org/gimps/p95v285.MacOSX.zip"
82 | url_prime95="https://github.com/qnxor/macoh/raw/master/mprime.tgz"
83 | url_gputest="http://www.ozone3d.net/gputest/dl/GpuTest_OSX_x64_0.7.0.zip"
84 | # Referer needed or else we get a 403
85 | url_gputest_referer="http://www.geeks3d.com/20140304/gputest-0-7-0-opengl-benchmark-win-linux-osx-new-fp64-opengl-4-test-and-online-gpu-database/"
86 | url_im="https://github.com/qnxor/macoh/raw/master/ImageMagick.tgz"
87 | url_gfx="https://github.com/qnxor/macoh/raw/master/gfxCardStatus.tgz"
88 |
--------------------------------------------------------------------------------
/macoh.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # GitHub project: https://github.com/qnxor/macoh
4 | # Bogdan Roman, University of Cambridge
5 | # http://www.damtp.cam.ac.uk/research/afha/bogdan
6 | #
7 |
8 | set -e
9 |
10 | # Default vars. DO NOT CHANGE THESE. Edit macoh.conf instead.
11 |
12 | home=~/macoh
13 | usercmd=''
14 | usercmdduration=300
15 | waitstart=15
16 | waitend=15
17 | ipgpoll=500
18 | gputest=tess_x64
19 | gpuwidth=1280
20 | gpuheight=720
21 | gpumsaa=2
22 | gpuduration=600
23 | gpunice=-10
24 | p95min=8
25 | p95max=8
26 | p95mem=0
27 | p95time=5
28 | p95duration=300
29 | p95nice=0
30 | fftduration=300
31 | fftsize=2048
32 | fftthreads=-1
33 | ffttype=0
34 | fftwisdom=0
35 | fftnice=-10
36 | hbnice=-10
37 | menuquit=0
38 | mov=big_buck_bunny_1080p_h264.mov
39 | mkv=/dev/null
40 | # mkv=$home/big_buck_bunny_1080p_h264_transcoded.mkv
41 | gputesttypes='fur, tess_x8, tess_x16, tess_x32, tess_x64, gi, pixmark_piano, pixmark_volplosion, plot3d, triangle'
42 | url_ipg="https://software.intel.com/file/613985/download"
43 | url_handbrake="http://download.handbrake.fr/releases/0.9.9/HandBrake-0.9.9-MacOSX.6_CLI_x86_64.dmg"
44 | url_gle="http://heanet.dl.sourceforge.net/project/glx/gle4%20(Current%20Active%20Version)/4.2.4c/gle-graphics-4.2.4c-exe-mac.dmg"
45 | url_video="http://blender-mirror.kino3d.org/peach/bigbuckbunny_movies/big_buck_bunny_1080p_h264.mov"
46 | # url_prime95="ftp://mersenne.org/gimps/p95v285.MacOSX.zip"
47 | url_prime95="https://github.com/qnxor/macoh/raw/master/mprime.tgz"
48 | url_gputest="http://www.ozone3d.net/gputest/dl/GpuTest_OSX_x64_0.7.0.zip"
49 | url_gputest_referer="http://www.geeks3d.com/20140304/gputest-0-7-0-opengl-benchmark-win-linux-osx-new-fp64-opengl-4-test-and-online-gpu-database/"
50 | url_gfx="https://github.com/qnxor/macoh/raw/master/gfxCardStatus.tgz"
51 | url_im="http://www.imagemagick.org/download/binaries/ImageMagick-x86_64-apple-darwin13.1.0.tar.gz"
52 |
53 |
54 | #------------------------------ Core functions ------------------------------#
55 |
56 | moh-init () {
57 | # Internal vars
58 | [[ -n $1 ]] && testid=$1 || testid=`date +%Y%m%d-%H%M%S`
59 | duration=0
60 | hduration=0
61 | code=''
62 | tmp="$home/tmp"
63 | bin="$home/bin"
64 | logs="$home/logs"
65 | ipgcsv="$logs/$testid-ipg.csv"
66 | hblog="$logs/$testid-hb.log"
67 | gpucsv="$logs/$testid-gputest.csv"
68 | gpulog="$logs/$testid-gputest.log"
69 | fftlog="$logs/$testid-fft.log"
70 | # Create needed dirs
71 | mkdir -p "$home" "$logs" "$tmp" "$bin"
72 | }
73 | die () {
74 | local code=$1; shift; echo "Error: $@." >&2; exit $code
75 | }
76 | err () {
77 | local code=$1; shift; echo "Error: $@." >&2; return $code
78 | }
79 | mnt () {
80 | hdiutil attach "$1" >/dev/null
81 | }
82 | umnt () {
83 | diskutil unmount "$1" >/dev/null
84 | }
85 | wget () {
86 | curl -L -o "$@"
87 | }
88 | stddev () {
89 | # awk '{ delta = $1 - avg; avg += delta / NR; mean2 += delta * ($1 - avg); } END { print sqrt(mean2 / NR); }'
90 | awk '{sum+=$1; sumsq+=$1*$1} END {print sqrt(sumsq/NR - (sum/NR)**2)}'
91 | }
92 | mean () {
93 | awk '{ delta = $1 - avg; avg += delta / NR; } END { print avg; }'
94 | }
95 | humantime () {
96 | [[ $t -ge 86400 ]] && echo -n $(($1/86400))d
97 | [[ $1 -ge 3600 ]] && echo -n $((($1%86400)/3600))h
98 | # [[ $1 -ge 60 ]] && echo -n $((($1%3600)/60))m
99 | echo $((($1%3600)/60))m$(($1%60))s
100 | }
101 | editconf () {
102 | local val re=$' \t\n'
103 | [[ $2 =~ $re ]] && val="'$2'" || val=$2
104 | eval "$1=$val"
105 | if [[ -r "$conf" ]] && grep -qE "^$1=" "$conf"; then
106 | cp -f "$conf" "$conf~"
107 | sed -E "s:^$1=[^[:space:]]+:$1=${val//:/\\:}:" "$conf~" > "$conf"
108 | else
109 | echo "$1=$val" >> "$conf"
110 | fi
111 | }
112 | silentkill () {
113 | # Die with dignity. Kill if stubborn.
114 | # Add brackets ( ) around bg processes so we suppress "stopped" messsages
115 | ( { sleep 0.25; kill -TERM $* &>/dev/null; } & )
116 | ( { sleep 5; kill -KILL $* &>/dev/null; } & )
117 | # The 'wait' trick only works for subprocess of the current shell, should be fine
118 | # It suppresses the "terminated" background messages.
119 | # "wait" returns 127 if process not found (thanks!). We return 0 always.
120 | wait $* &>/dev/null || return 0
121 | }
122 | set-imagick () {
123 | local im
124 | if [[ -d $bin/ImageMagick ]]; then
125 | export MAGICK_HOME="$bin/ImageMagick"
126 | export DYLD_LIBRARY_PATH="$MAGICK_HOME/lib/"
127 | [[ "$PATH" = *"$MAGICK_HOME/bin"* ]] || export PATH="$MAGICK_HOME/bin:$PATH"
128 | fi
129 | }
130 | anykey () {
131 | local msg="Press any key to continue ..."
132 | [[ -n $1 ]] && msg="$@"
133 | echo $msg
134 | read -s -n 1
135 | }
136 | # Fetch a list of functions prefixed by PREFIX. Outputs a list separated by SEP
137 | # Usage: functionlist PREFIX SEP
138 | functionlist () {
139 | local IFS=$'\n\t '
140 | local list=(`declare -f | grep -Eo "^$1[a-zA-Z0-9_\-]+ \(\)" | sed -E "s/^$1//;s/ \(\)//"`)
141 | list=${list[*]}
142 | echo ${list// /$2}
143 | }
144 | menu () {
145 | local i n ans map prompt=$1 default=$2
146 | local args=$@
147 | shift 2
148 | local opts=("$@")
149 | while [[ 1 ]]; do
150 | i=0
151 | n=0
152 | map=''
153 | while [[ $i -lt $# ]]; do
154 | if [[ -z ${opts[i]} ]]; then
155 | echo
156 | else
157 | let n=n+1
158 | printf " %2d. %s\n" $n ${opts[i]}
159 | map=("${map[@]}" "${opts[i]}")
160 | fi
161 | let i=i+1
162 | done
163 | echo
164 | echo -n "$prompt"
165 | [[ -n $default ]] && echo -n " [$default] "
166 | read ans
167 | echo
168 | if [[ -z $ans ]]; then
169 | menuchoice="$default"
170 | break
171 | elif [[ $ans -ge 1 && $ans -le $n ]]; then
172 | menuchoice=${map[ans]}
173 | break
174 | else
175 | anykey "Invalid choice '$ans'. Press any key to try again ..."
176 | echo
177 | fi
178 | done
179 | }
180 | benice () {
181 | local pid
182 | echo "Changing $1's niceness to $2 ..."
183 | for ((i=0;i<120;i++)); do
184 | sleep 1
185 | pid=`pgrep $1` && {
186 | sleep 2
187 | sudo renice $2 -p $pid
188 | break
189 | }
190 | done
191 | }
192 | getfuncdef () {
193 | declare -f $1
194 | }
195 | freemb () {
196 | local IFS=$'\n\t .'
197 | local page=(`vm_stat | grep -oE "page size of [0-9]+ bytes" 2>/dev/null`)
198 | local free=(`vm_stat | grep "^Pages free:" 2>/dev/null`)
199 | IFS=$'\n\t '
200 | page=${page[3]}
201 | free=${free[2]}
202 | [[ $page -gt 0 && $free -gt 0 ]] || { echo && return 0; }
203 | free=`echo "($page*$free)/1048576" | bc -l`
204 | echo ${free/.*/}
205 | }
206 | getphycores () {
207 | sysctl -n hw.physicalcpu
208 | }
209 | getlogicalcores () {
210 | sysctl -n hw.logicalcpu
211 | }
212 | getthreads () {
213 | if [[ $1 -lt 0 ]]; then
214 | local t=$((`getphycores`-1))
215 | [[ $t -lt 1 ]] && echo 1 || echo $t
216 | elif [[ $1 = 0 ]]; then
217 | getlogicalcores
218 | else
219 | echo $1
220 | fi
221 | }
222 | strcmp () {
223 | [[ "$1" = "$2" ]] && return 0 || return 1
224 | }
225 | strcmpi () {
226 | shopt -s nocasematch
227 | [[ "$1" = "$2" ]]
228 | local x=$?
229 | shopt -u nocasematch
230 | return $x
231 | }
232 | regexp () {
233 | [[ "$1" =~ "$2" ]] && return 0 || return 1
234 | }
235 | regexpi () {
236 | shopt -s nocasematch
237 | [[ "$1" =~ "$2" ]]
238 | local x=$?
239 | shopt -u nocasematch
240 | return $x
241 | }
242 |
243 | #------------------------------ GET functions ------------------------------#
244 |
245 |
246 | moh-get-handbrake ()
247 | {
248 | echo
249 | local ans=y
250 | # md5=d426eae09825284c8a4b66d55cafeeb4
251 | [[ -x $bin/HandBrakeCLI && $1 != force ]] && \
252 | read -p "HandBrake CLI seems to exist in $bin. Redownload? [n] " ans
253 | if [[ $ans = y || $ans = Y ]]; then
254 | set -e
255 | rm -f $bin/done-handbrake
256 | echo Fetching HandBrake CLI into $bin ...
257 | wget $tmp/HandBrake-0.9.9-MacOSX.6_CLI_x86_64.dmg "$url_handbrake" -#
258 | mnt $tmp/HandBrake-0.9.9-MacOSX.6_CLI_x86_64.dmg
259 | cp -f /Volumes/HandBrake-0.9.9-MacOSX.6_CLI_x86_64/HandBrakeCLI $bin
260 | umnt /Volumes/HandBrake-0.9.9-MacOSX.6_CLI_x86_64
261 | > $bin/done-handbrake
262 | fi
263 | }
264 |
265 | moh-get-ipg ()
266 | {
267 | echo
268 | local ans=y
269 | # md5=5e3f984efdf04fa608ef1ba35d1309fe
270 | [[ -d /Applications/Intel\ Power\ Gadget && $1 != force ]] && read -p "Intel Power Gadget seems to be installed. Redownload? [n] " ans
271 | if [[ $ans = y || $ans = Y ]]; then
272 | set -e
273 | rm -f $bin/done-ipg
274 | echo "Fetching and installing Intel Power Gadget into /Applications ..."
275 | wget $tmp/ipg.dmg "$url_ipg" -#
276 | mnt $tmp/ipg.dmg
277 | echo "Installing Intel Power Gadget may ask you to enter your Mac password."
278 | sudo installer -pkg /Volumes/Intel*\ Power\ Gadget/Install\ Intel\ Power\ Gadget.pkg -target /
279 | umnt /Volumes/Intel*\ Power\ Gadget
280 | > $bin/done-ipg
281 | fi
282 | }
283 |
284 | moh-get-gle ()
285 | {
286 | echo
287 | local ans=y
288 | # md5=021e612a678cce8f2f8b1425fec1d0b5
289 | [[ -d $bin/QGLE.app && $1 != force ]] && read -p "QGLE seems to be installed. Redownload? [n] " ans
290 | if [[ $ans = y || $ans = Y ]]; then
291 | set -e
292 | rm -f $bin/done-gle
293 | echo Fetching Graphics Layout Engine into $bin ...
294 | wget $tmp/gle.dmg "$url_gle" -#
295 | mnt $tmp/gle.dmg
296 | [[ -d $bin/QGLE.app ]] && rm -rf $bin/QGLE.app
297 | cp -r /Volumes/gle-graphics-*/QGLE.app $bin
298 | umnt /Volumes/gle-graphics-*
299 | > $bin/done-gle
300 | fi
301 | }
302 |
303 | moh-get-video ()
304 | {
305 | echo
306 | local ans=y
307 | # md5=c23ab2ff12023c684f46fcc02c57b585
308 | [[ -r $home/$mov && $1 != force ]] && read -p "The video file seems exist in $home. Redownload? [n] " ans
309 | if [[ $ans = y || $ans = Y ]]; then
310 | set -e
311 | rm -f $home/done-video
312 | echo "Fetching The Big Buck Bunny movie (692 MB) into $home. This may take a while ..."
313 | wget $home/$mov "$url_video" -#
314 | > $home/done-video
315 | fi
316 | }
317 |
318 | moh-get-prime95 ()
319 | {
320 | echo
321 | local ans=y
322 | # md5=0390ae2ff3d4a7082927482d82e62f59
323 | [[ -x $bin/mprime && $1 != force ]] && \
324 | read -p "Prime95 seems to be installed. Redownload? [n] " ans
325 | if [[ $ans = y || $ans = Y ]]; then
326 | set -e
327 | rm -f $bin/done-prime95 $bin/mprime
328 | echo Fetching Prime95 into $bin ...
329 | wget $tmp/mprime.tgz "$url_prime95" -#
330 | tar -C $bin -zxf $tmp/mprime.tgz
331 | > $bin/done-prime95
332 | fi
333 | }
334 |
335 | moh-get-gputest ()
336 | {
337 | echo
338 | local ans=y
339 | # md5=b3dbe739f64336b1f0752149c495dbf4
340 | [[ -d $bin/GpuTest.app && $1 != force ]] && \
341 | read -p "GpuTest seems to be installed. Redownload? [n] " ans
342 | if [[ $ans = y || $ans = Y ]]; then
343 | set -e
344 | rm -f $bin/done-gputest
345 | echo Fetching GpuTest into $bin ...
346 | wget $tmp/gputest.zip "$url_gputest" -# --referer "$url_gputest_referer"
347 | unzip -q -o $tmp/gputest.zip -d $tmp
348 | [[ -d $bin/GpuTest.app ]] && rm -rf $bin/GpuTest.app
349 | cp -rf $tmp/GpuTest.app $bin
350 | rm -rf $tmp/GpuTest.app
351 | chmod 755 $bin/GpuTest.app/Contents/MacOS/GpuTest
352 | > $bin/done-gputest
353 | fi
354 | }
355 |
356 | moh-get-gfx ()
357 | {
358 | echo
359 | local ans=y
360 | # md5=1cecb1974a1d5c374dfd180a5e7b828e
361 | # [[ ( -d $bin/gfxCardStatus.app || -d /Applications/gfxCardStatus.app ) && $1 != force ]] && \
362 | [[ -d $bin/gfxCardStatus.app && $1 != force ]] && \
363 | read -p "gfxCardStatus seems to be installed. Redownload? [n] " ans
364 | if [[ $ans = y || $ans = Y ]]; then
365 | set -e
366 | rm -f $bin/done-gfx
367 | echo Fetching gfxCardStatus into $bin ...
368 | wget $tmp/gfxCardStatus.tgz "$url_gfx" -#
369 | [[ -d $bin/gfxCardStatus.app ]] && rm -rf $bin/gfxCardStatus.app
370 | tar -C $bin -zxf $tmp/gfxCardStatus.tgz
371 | > $bin/done-gfx
372 | fi
373 | }
374 |
375 | # Fetch and install a local copy of ImageMagick
376 | moh-get-imagick ()
377 | {
378 | echo
379 | local d ans=y
380 | # md5=1cecb1974a1d5c374dfd180a5e7b828e
381 | [[ -d $bin/ImageMagick-* && $1 != force ]] && \
382 | read -p "ImageMagick seems to be installed. Redownload? [n] " ans
383 | if [[ $ans = y || $ans = Y ]]; then
384 | set -e
385 | rm -f $bin/done-imagick
386 | echo Fetching ImageMagick into $bin ...
387 | wget $tmp/imagemagick.tgz "$url_im" -#
388 | tar -C $bin -zxf $tmp/imagemagick.tgz
389 | mv $bin/ImageMagick-* $bin/ImageMagick
390 | > $bin/done-imagick
391 | fi
392 | set-imagick
393 | }
394 |
395 | #---------------------------- DO/CHECK functions ----------------------------#
396 |
397 | # Check mandatory packages
398 | moh-check-common () {
399 | [[ -r $bin/done-ipg && -d /Applications/Intel\ Power\ Gadget ]] || moh-get-ipg force
400 | [[ -r $bin/done-gle && -d $bin/QGLE.app ]] || moh-get-gle force
401 | [[ -r $bin/done-imagick && -d $bin/ImageMagick ]] || moh-get-imagick force
402 | }
403 |
404 | # Check if all x264 test dependencies exist and download/install if not
405 | moh-check-x264 ()
406 | {
407 | moh-check-common
408 | [[ -r $bin/done-handbrake && -x $bin/HandBrakeCLI ]] || moh-get-handbrake force
409 | [[ -r $home/done-video && -r $home/$mov ]] || moh-get-video force
410 | }
411 |
412 | # Check if all Prime95 test dependencies exist and download/install if not
413 | moh-check-prime95 ()
414 | {
415 | moh-check-common
416 | [[ -r $bin/done-prime95 && -x $bin/mprime ]] || moh-get-prime95 force
417 | }
418 |
419 | # Check if all Prime95 test dependencies exist and download/install if not
420 | moh-check-gputest ()
421 | {
422 | moh-check-common
423 | [[ -r $bin/done-gputest && -d $bin/GpuTest.app ]] || moh-get-gputest force
424 | }
425 |
426 | # Check packages for the FFT test
427 | moh-check-fft ()
428 | {
429 | moh-check-common
430 | }
431 |
432 | # Check packages for a user defined command
433 | moh-check-usercmd ()
434 | {
435 | moh-check-common
436 | }
437 |
438 | # Check packages for a user defined command
439 | moh-check-gfx ()
440 | {
441 | [[ -r $bin/done-gfx && -d $bin/gfxCardStatus.app ]] || moh-get-gfx force
442 | }
443 |
444 | ## Start any user specified command and log it (it must terminate)
445 | ## TODO: add timer
446 | moh-cmd ()
447 | {
448 | do=usercmd
449 | moh-check-usercmd
450 | echo "$usercmd" | moh-wrapper UserCmd $usercmdduration
451 | }
452 |
453 | ## Do my FFTW test
454 | moh-do-fft ()
455 | {
456 | do=fft
457 | moh-check-fft
458 | local cmd="$(dirname $0)/fftwtest"
459 | local threads=`getthreads $fftthreads`
460 | chmod +x "$cmd"
461 | moh-wrapper FFT <<-SH
462 | echo
463 | sudo nice -n $fftnice "$cmd" $fftduration $threads $fftsize $ffttype $fftwisdom 2>&1 | tee $fftlog
464 | echo
465 | SH
466 | }
467 |
468 | # Run GpuTest
469 | moh-do-gputest ()
470 | {
471 | do=gputest
472 | moh-check-gputest
473 | local sudo
474 | [[ $gpunice -lt 0 ]] && sudo=sudo
475 | moh-wrapper GpuTest <<-SH
476 | $(getfuncdef benice)
477 | benice GpuTest $gpunice &
478 | $bin/GpuTest.app/Contents/MacOS/GpuTest '/test=$gputest /width=$gpuwidth /height=$gpuheight /msaa=$gpumsaa /benchmark /benchmark_duration_ms=${gpuduration}000 /no_scorebox' &>/dev/null
479 | SH
480 | }
481 |
482 | # Run Prime95 ... currently buggy, torture test does not always start with -t
483 | # http://www.mersenneforum.org/showthread.php?p=372979#post372918
484 | moh-do-prime95 ()
485 | {
486 | do=prime95
487 | moh-check-prime95
488 |
489 | # local workdir=~/Prime95
490 | # [[ -d $workdir ]] && rm -rf $workdir
491 | # mkdir -p $workdir
492 |
493 | # cat <<-STR
494 |
495 | # ---------------
496 | # W A R N I N G
497 | # ---------------
498 |
499 | # There is a bug in Prime95, the torture test does not start automatically when the GUI opens. For now, do it manually once the GUI opens as follows:
500 |
501 | # Options -> Torture Test -> Custom -> MinFFT=$p95min, MaxFFT=$p95max, Memory=$p95mem, Time=$p95time -> Run.
502 |
503 | # Press any key to start Prime95 ...
504 |
505 | # STR
506 | # read -s -n 1
507 |
508 | # Small in-place: Min=8,Max=8,Mem=8 (in-place when TortureMem = 0)
509 | # Large in-place: Min=128,Max=1024,Mem=8 (in-place when TortureMem = 0)
510 | # Blend: Min=8, Max=1792, Mem=2048
511 | # For small with some mem: Min=8, Max=16, Mem=512, Time=5
512 | cat > $bin/prime.txt <<-TXT
513 | V24OptionsConverted=1
514 | WGUID_version=2
515 | StressTester=1
516 | UsePrimenet=0
517 | MinTortureFFT=$p95min
518 | MaxTortureFFT=$p95max
519 | TortureMem=$p95mem
520 | TortureTime=$p95time
521 | Nice=$p95nice
522 |
523 | [PrimeNet]
524 | Debug=0
525 | TXT
526 | # ManualComm=1
527 | # SumInputsErrorCheck=0
528 | # ErrorCheck=0
529 | # StaggerStarts=1
530 | # MergeWindows=12
531 | # NoMoreWork=0
532 |
533 | moh-wrapper Prime95 $p95duration <<-SH
534 | echo
535 | # $bin/mprime -t -W$bin | sed -E '/Please read|Beginning a|Worker starting|Setting affinity/d'
536 | $bin/mprime -t -W$bin
537 | echo
538 | SH
539 | }
540 |
541 | ## Start the normal x264 test
542 | moh-do-x264 () {
543 | do=x264
544 | moh-check-x264
545 | # HandBrake changes its nice level to 19 after it starts so we can't start
546 | # it with nice -n 0 HandBrakeCLI. Prepend a background process to poll for
547 | # it and renice it once detected
548 | # NOTE: starting with nice is not a good idea since negative values require
549 | # sudo which then causes HB to place the log files in /root ...
550 | moh-wrapper x264 <<-SH
551 | $(getfuncdef benice)
552 | benice HandBrakeCLI $hbnice &
553 | $bin/HandBrakeCLI -i $home/$mov -o $mkv -f mkv -4 -w 1280 -l 720 -e x264 -q 26 --vfr -a 1 -E ffaac -B 128 -6 stereo -R Auto -D 0 --gain=0 --audio-copy-mask none --audio-fallback ffaac -x rc-lookahead=50:ref=8:bframes=16:me=umh:subme=9:merange=24 --verbose=1 2>$hblog
554 | SH
555 | }
556 |
557 | ## Start the long x264 test
558 | moh-do-x264-long () {
559 | do=x264-long
560 | moh-check-x264
561 | moh-wrapper x264-Long <<-SH
562 | $(getfuncdef benice)
563 | benice HandBrakeCLI $hbnice &
564 | # $bin/HandBrakeCLI -i $home/$mov -o $mkv -f mkv -4 -w 1280 -l 720 -e x264 -q 20 --vfr -a 1 -E ffaac -B 128 -6 stereo -R Auto -D 0 --gain=0 --audio-copy-mask none --audio-fallback ffaac -x rc-lookahead=50:ref=16:bframes=16:b-adapt=2:direct=auto:me=tesa:subme=11:merange=48:analyse=all:trellis=2 --verbose=1 2>$hblog
565 | # $bin/HandBrakeCLI -i $home/$mov -o $mkv -f mkv -4 -w 1280 -l 720 -e x264 -q 20 --vfr -a 1 -E ffaac -B 128 -6 stereo -R Auto -D 0 --gain=0 --audio-copy-mask none --audio-fallback ffaac --x264-preset=veryslow --verbose=1 2>$hblog
566 | $bin/HandBrakeCLI -i $home/$mov -o $mkv -f mkv -4 -w 1280 -l 720 -e x264 -q 26 --vfr -a 1 -E ffaac -B 128 -6 stereo -R Auto -D 0 --gain=0 --audio-copy-mask none --audio-fallback ffaac -x rc-lookahead=200:ref=16:bframes=16:b-adapt=2:direct=auto:me=esa:subme=9:merange=24 --verbose=1 2>$hblog
567 | SH
568 | }
569 |
570 | moh-do-gfx () {
571 | do=gfx
572 | open "$bin/gfxCardStatus.app"
573 | echo "gfxCardStatus started, it should appear on the menu bar. Click it to select which GPU to use for 3D if you have both an integrated and discrete GPU."
574 | }
575 |
576 | moh-do-plot () {
577 | do=plot
578 | moh-plot $testid
579 | }
580 |
581 | #--------------------------- AUXILIARY functions ---------------------------#
582 |
583 | moh-gpudetect () {
584 | moh-check-gfx
585 | local i j log pid
586 | $bin/gfxCardStatus.app/Contents/MacOS/gfxCardStatus &> $tmp/gfx.log &
587 | pid=$!
588 | echo Detecting GPUs ...
589 | for ((i=0;i<10;i++)); do
590 | sleep 1
591 | log=$(<$tmp/gfx.log)
592 | if [[ "$log" =~ GPUs\ present:\ \([^\)]+$'\n'\) ]]; then
593 | log=${log/*GPUs present: (/}
594 | log=${log/)*/}
595 | log="${log//[\",]/}"
596 | local IFS=$'\n'
597 | log=($log)
598 | local IFS=$'\n\t '
599 | if [[ ${#log[*]} -lt 2 ]]; then
600 | silentkill $pid
601 | echo "Only one GPU detected. Nothing to switch. Exiting ..." >&2
602 | return 15
603 | else
604 | # for ((j=0;j<${#log[*]};j++)); do echo $((j+1)). ${log[j]}; done
605 | silentkill $pid
606 | return 0
607 | fi
608 | fi
609 | done
610 | silentkill $pid
611 | echo Timeout waiting for gfxCardStatus. >&2
612 | return 16
613 | }
614 |
615 | # moh-gpuswitch MODE, where MODE={1,2,3} for integrated, discrete, dynamic
616 | moh-gpuswitch () {
617 | moh-check-gfx
618 | moh-gpudetect || return $?
619 | local i j log pid arg n=2 name=$1 line readouts finished size logfile=$logs/gfx.log
620 | arg=`echo $1 | tr '[:upper:]' '[:lower:]'`
621 | [[ $1 = 1 ]] && arg=integrated && name=Integrated
622 | [[ $1 = 2 ]] && arg=discrete && name=Discrete
623 | [[ $1 = 3 ]] && arg=dynamic && name=Dynamic
624 | [[ $arg =~ ^integrated|discrete|dynamic$ ]] \
625 | || die $ERR_GPUSWITCH "Invalid GPU switch parameter '$arg'. GPU not switched."
626 | echo Switching GPU to $name ...
627 | # Need to attempt 2-3 times due to a bug
628 | # https://github.com/codykrieger/gfxCardStatus/issues/103
629 | for ((i=1;i<=n;i++)); do
630 | echo Pass $i/$n ...
631 | # It also doesn't exit, so we need to background it, monitor its log file, then kill it ...
632 | > $logfile
633 | $bin/gfxCardStatus.app/Contents/MacOS/gfxCardStatus --$arg &> $logfile &
634 | pid=$!
635 | # stop when file size stops increasing
636 | for ((j=0;j<10;j++)); do
637 | [[ $j = 0 ]] && sleep 1 || sleep 1
638 | size[1]=`wc -c $logfile`
639 | [[ ${size[0]} = ${size[1]} ]] && break
640 | size[0]=${size[1]}
641 | # for ((j=0;j&2 && return $ERR_GPUSWITCH
650 | # echo killing pid=$pid $i
651 | silentkill $pid
652 | done
653 | echo "Done. GPU should now be switched to $name. "
654 | }
655 |
656 | moh-gpuswitch-menu () {
657 | moh-check-gfx
658 | moh-gpudetect || return $?
659 | echo
660 | menu "Choose GPU:" Abort Integrated Discrete Dynamic "" Abort
661 | [[ $menuchoice = Abort ]] && return 0
662 | moh-gpuswitch $menuchoice
663 | anykey
664 | }
665 |
666 | ## Parse Prime95 log and populate the global $duration, $mins, $secs, $perf
667 | ## For now it does nothing since Prime95 is killed forcefully as it lacks a
668 | ## stop condition
669 | moh-perf-prime95 () {
670 | perf="min:$p95min, max:$p95max, mem:$p95mem, time:$p95time"
671 | testname=Prime95
672 | }
673 |
674 | ## Parse HandBrake log and populate the global $duration, $mins, $secs, $perf
675 | moh-perf-x264 () {
676 | [[ -r $hblog ]] || return 0
677 | local frames=(`grep -Eo 'got [0-9]+ frames' $hblog`)
678 | frames=${frames[1]}
679 | local fps=(`grep -Eo 'average encoding speed for job is [0-9.]+ fps' $hblog`)
680 | fps=${fps[6]}
681 | duration=`echo "$frames/$fps" | bc -l`
682 | duration=${duration/.*/}
683 | hduration=`humantime $duration`
684 | perf="${fps:0:5} fps"
685 | testname=x264
686 | }
687 |
688 | moh-perf-x264-long () {
689 | moh-perf-x264
690 | testname=x264-Long
691 | }
692 |
693 | ## Populate the graph title for the FFTW test
694 | moh-perf-fft () {
695 | local ffts
696 | [[ -r $fftlog ]] && ffts=`grep -Eo "[0-9.]+ ffts/sec" $fftlog`
697 | perf="threads:$(getthreads $fftthreads), size:$fftsize, type:$ffttype, wisdom:$fftwisdom"
698 | [[ -n $ffts ]] && perf="$perf, $ffts"
699 | testname=FFT
700 | }
701 |
702 | ## Parse GpuTest log and populate the global $duration, $mins, $secs, $perf
703 | moh-perf-gputest () {
704 | [[ -r $gpucsv ]] || return 0
705 | local IFS=$'\n\t,'
706 | local csv=($(<$gpucsv))
707 | local IFS=$'\n\t '
708 | local n=${#csv[*]}
709 | local frames=${csv[n-1]}
710 | duration=$((csv[n-3]/1000))
711 | hduration=`humantime $duration`
712 | local gpu=${csv[n-10]}
713 | gpu=${gpu/ OpenGL Engine/}
714 | gpu=${gpu/NVIDIA/Nvidia}
715 | gpu=${gpu/GeForce /}
716 | local fps=`echo "$frames/$duration" | bc -l`
717 | perf="${fps:0:5} fps, ${gpuwidth}x$gpuheight, ${gpumsaa}xAA, $gpu"
718 | testname=GpuTest
719 | }
720 |
721 | ## Wrapper to start, monitor and log any job which is read from stdin
722 | ## usage wrapper NAME TIMEOUT
723 | ## - NAME is a short no-spaces name of the job, e.g. x264-long
724 | ## - TIMEOUT is a duration in seconds after which the test is forcefully killed
725 | ## Use 0 to disable the timeout.
726 | moh-wrapper ()
727 | {
728 | echo
729 |
730 | # set test name (displayed in the graph title)
731 | local testname=$1
732 |
733 | # Prepare script file to pass to Intel Power Gadget
734 | local cmdfile=$tmp/cmd-$do.sh
735 |
736 | local code=$(/dev/null & } && kill -TERM $pids; ) &>/dev/null &
750 | # ( { sleep '$2'; pids=`pgrep -P $$ 2>/dev/null` && silentkill $pids; } & )
751 | '
752 |
753 | # Is the code using sudo? If so, ask for the password now to avoid the
754 | # password prompt being ocluded later by the wrapping scripts which may
755 | # redirect stdout/stderr.
756 | local needsudo=`sudo -n echo foo 2>/dev/null`
757 | [[ $code =~ sudo && $needsudo != foo ]] && {
758 | echo Your password is needed to run the test in elevated mode.
759 | sudo echo
760 | }
761 |
762 | # Build script file to pass to Intel Power Gadget
763 | cat > $cmdfile <<-SH
764 | #!/bin/bash
765 | {
766 | echo Waiting $waitstart seconds to capture idle temperature ...
767 | sleep $waitstart
768 | echo Starting $testname benchmark. It may take a while and fans may go berserk ...
769 | $watchdog
770 | $code
771 | echo Test finished. Cooling off for $waitend seconds ...
772 | sleep $waitend
773 | } >&2
774 | SH
775 | chmod 700 $cmdfile
776 |
777 | # Finally ... Go!
778 | local timestart=$(date +%s)
779 | > $tmp/ipgvals.log
780 | #script -q /dev/null \
781 | /Applications/Intel\ Power\ Gadget/PowerLog -resolution $ipgpoll \
782 | -file $ipgcsv -cmd $cmdfile > $tmp/ipgvals.log
783 | local timeend=$(date +%s)
784 |
785 | # Don't do these in $code because the user may press Ctrl-C
786 | [[ $do =~ gputest ]] && {
787 | [[ -r ~/_geeks3d_gputest_log.txt ]] && mv ~/_geeks3d_gputest_log.txt $gpulog
788 | [[ -r ~/_geeks3d_gputest_scores.csv ]] && mv ~/_geeks3d_gputest_scores.csv $gpucsv
789 | }
790 |
791 | # Populate the global $duration, $mins, $secs
792 | duration=$((timeend-timestart-waitstart-waitend))
793 | hduration=`humantime $duration`
794 |
795 | # Plot result
796 | moh-plot $testname
797 | }
798 |
799 | # Plot
800 | moh-plot () {
801 | local testname=$1
802 |
803 | # Prepare to plot graph from the csv output of IPG
804 | cat >$tmp/ipg.gle <<-'GLE'
805 | papersize 20 10
806 | size 20 10
807 | !margins 2 2 2 2
808 | set font texcmss
809 | set titlescale 1
810 | !set texlabels 1
811 | Tmax = arg(6)
812 | Tmax2 = 0.95*Tmax
813 | TDP = arg(7)
814 | begin graph
815 | title arg$(2) dist 0.5
816 | xtitle "Time (sec)"
817 | x2axis off
818 | y2title "CPU Frequency (MHz)" color blue
819 | ! y2side color blue
820 | axis grid
821 | subticks on
822 | ticks color rgb255(224,224,224)
823 | subticks lstyle 2
824 | subticks color rgb255(224,224,224)
825 | yaxis min 0 max 120 dticks 10 dsubticks 3.3333
826 | y2axis min 400 max 4000 dticks 300 ftick 400
827 | ! xnames from d1
828 | ! key pos bl nobox offset 2.5 0.25
829 | data arg$(1) ignore 1 d1=c1,c9 d2=c1,c2 d3=c1,c3
830 | ! d1 line color red key arg$(3)
831 | ! d2 x2axis y2axis line color !blue key ""+arg$(5)+""
832 | ! d3 line color green key arg$(4)
833 | d1 line color red
834 | d2 x2axis y2axis line color blue
835 | d3 line color green
836 | let d4 = Tmax
837 | !let d5 = Tmax2
838 | let d6 = TDP
839 | d4 lstyle 2 color red
840 | !d5 lstyle 2 color red
841 | d6 lstyle 2 color green
842 | end graph
843 |
844 | begin key
845 | position bl
846 | !nobox
847 | offset 2.5 0.25
848 | line color red text arg$(3)
849 | line color blue text arg$(5)
850 | line color green text arg$(4)
851 | end key
852 |
853 | ! Left axis labels, we want multiple colors so we
854 | ! use tex instead of ytitle
855 |
856 | amove xg(xgmax/100) yg(Tmax+1)
857 | set color red
858 | write "Tmax="+format$(Tmax,"fix 1")+"C"
859 |
860 | !amove xg(xgmax/100) yg(Tmax2+1)
861 | !set color red
862 | !tex "0.95 Tmax" name tmax2
863 |
864 | amove xg(xgmax/100) yg(TDP+1)
865 | set color green
866 | write "TDP="+format$(TDP,"fix 1")+"W"
867 |
868 | amove 2.1 2.25
869 | set color green
870 | begin rotate 90
871 | write "CPU Power (W)"
872 | end rotate
873 |
874 | amove 2.1 4.9
875 | set color black
876 | begin rotate 90
877 | write ","
878 | end rotate
879 |
880 | amove 2.1 5.25
881 | set color red
882 | begin rotate 90
883 | write "CPU Temp (C)"
884 | end rotate
885 | GLE
886 |
887 | # graph files
888 | local graph=$home/$testid-$do.png
889 | local graphgif=$home/$testid-$do.gif
890 |
891 | # Read TDP from igp's report ... need to log stderr for that
892 | #TODO: log IGP stderr too
893 |
894 | # Remove the 11 trailing lines (Intel decided to add non-csv at athe end)
895 | # and the first two columns (there's a bug in GLE: it can't properly read
896 | # the xnames from a column different than 1st column;
897 | # "xnames from d1" reads the y values, instead of x values)
898 | local lines=(`wc -l "$ipgcsv"`)
899 | head -n $((${lines[0]}-11)) $ipgcsv | sed 's/^[^,]*,[^,]*,//' > $tmp/ipg.csv
900 | lines=(`wc -l $tmp/ipg.csv`)
901 |
902 | # Get max temp, max freq, duration and avg fps
903 | local maxtemp=`cut -f9 -d, $tmp/ipg.csv | sed 's/[[:space:]]//g' | sort -n | tail -1`
904 | local maxpow=`cut -f3 -d, $tmp/ipg.csv | sed 's/[[:space:]]//g' | sort -n | tail -1`
905 | local maxfreq=`cut -f2 -d, $tmp/ipg.csv | sed 's/[[:space:]]//g' | sort -n | tail -1`
906 | printf -v maxpow "%.1f" $maxpow
907 |
908 | # get TDP and Tmax
909 | local Tmax=`grep -oE '^Max Temp = [0-9.]+' $tmp/ipgvals.log`
910 | Tmax=${Tmax##* }
911 | [[ -n $Tmax ]] || Tmax=0
912 | local TDP=`grep -oE '^TDP.*= [0-9.]+' $tmp/ipgvals.log`
913 | TDP=${TDP##* }
914 | [[ -n $TDP ]] || TDP=0
915 |
916 | # idle period lines in the csv (skip these to compute avg,std)
917 | local linestart=$(((waitstart+2)*1000/ipgpoll))
918 | local lineend=$((lines-(waitend+2)*1000/ipgpoll))
919 | local readuseful="sed -n ${linestart},${lineend}p $tmp/ipg.csv"
920 |
921 | # Get mean and stddev for temp
922 | local avgfreq=`$readuseful | awk -F',' '{s+=$2} END {printf "%.0f\n", s/NR}'`
923 | local avgpow=`$readuseful | awk -F',' '{s+=$3} END {printf "%.1f\n", s/NR}'`
924 | local avgtemp=`$readuseful | awk -F',' '{s+=$9} END {printf "%.1f\n", s/NR}'`
925 | local stdfreq=`$readuseful | awk -F',' '{d=$2-'$avgfreq';s+=d*d} END {printf "%.0f\n", sqrt(s/NR)}'`
926 | local stdpow=`$readuseful | awk -F',' '{d=$3-'$avgpow';s+=d*d} END {printf "%.1f\n", sqrt(s/NR)}'`
927 | local stdtemp=`$readuseful | awk -F',' '{d=$9-'$avgtemp';s+=d*d} END {printf "%.1f\n", sqrt(s/NR)}'`
928 |
929 | # compute how much the Temp and Power are >= the limits
930 | local overlimpow=`$readuseful | awk -F',' '$3 > '$TDP' {s+=1} END {printf "%.1f%%\n", s/NR*100}'`
931 | local overlimtemp=`$readuseful | awk -F',' '$9 > 0.95*'$Tmax' {s+=1} END {printf "%.1f%%\n", s/NR*100}'`
932 |
933 | # Parse log files and extract perf and duration strings
934 | moh-perf-$do
935 | # Extract duration if it wasn't set in moh-perf-$do
936 | [[ -z $duration || $duration = 0 ]] && {
937 | duration=`cut -f1 -d, $tmp/ipg.csv | tail -n 1`
938 | printf -v duration "%.0f" $duration
939 | let duration=duration-waitstart-waitend
940 | hduration=`humantime $duration`
941 | }
942 |
943 | # Prepend to title, $testname shoul dbe set in moh-perf-$do (or before)
944 | local testtitle=$testname
945 | [[ $do = gputest ]] && testtitle="$testtitle ($gputest)"
946 |
947 | # CPU model
948 | local cpu=`sysctl -n machdep.cpu.brand_string`
949 | cpu=${cpu/ CPU/}
950 | cpu=${cpu/(TM)/}
951 | cpu=${cpu/(R)/}
952 | cpu=${cpu/Intel /}
953 | cpu=${cpu/AMD /}
954 |
955 | # Graph title
956 | local graphtitle="$testtitle - $cpu - $hduration"
957 | [[ -n $perf ]] && graphtitle="$graphtitle, $perf"
958 |
959 | # Plot graph, -resolution sets the DPI, note that the PNG driver is
960 | # a rasterized and resampled version of the internal Postscript output, and
961 | # as such, the values sometimes may appear slightly off due to resampling
962 | $bin/QGLE.app/Contents/bin/gle -cairo -resolution 200 -d png -verbosity 0 \
963 | -output $graph \
964 | $tmp/ipg.gle \
965 | $tmp/ipg.csv \
966 | "$graphtitle" \
967 | "Temp, max:${maxtemp}, avg:${avgtemp}, above 0.95Tmax:${overlimtemp}" \
968 | "Power, max:${maxpow}, avg:${avgpow}, above TDP:${overlimpow}" \
969 | "Freq, max:${maxfreq}, avg:${avgfreq}" \
970 | $Tmax \
971 | $TDP \
972 | >/dev/null
973 |
974 | # Crop and make smaller, use sips if ImageMagick is not available
975 | set-imagick
976 | if which convert &>/dev/null; then
977 | rm -f $graph-1
978 | mogrify -crop 1340x730+125+35 -quality 96 -colors 64 -write $graph-1 $graph \
979 | && mv $graph-1 $graph
980 | elif which sips &>/dev/null; then
981 | sips -s format gif $graph --out $graphgif &>/dev/null
982 | graph=$graphgif
983 | rm $graph
984 | fi
985 | rm -f $graph*~
986 |
987 | echo
988 | [[ -n $perf ]] && echo "Benchmark: $perf"
989 | cat <<-STR
990 | Max temp reached: $maxtemp C
991 | Test duration: $duration secs ($hduration)
992 |
993 | See $graph for the full graph.
994 |
995 | STR
996 |
997 | # open graph
998 | open $graph
999 | }
1000 |
1001 |
1002 | #--------------------------------- SCRIPT ---------------------------------#
1003 |
1004 |
1005 | # Error codes
1006 | ERR_CMDLINE=11
1007 | ERR_KILL=13
1008 | ERR_GPUSWITCH=19
1009 |
1010 |
1011 | # Parse conf file. Overrides defaults, but not cmd line options.
1012 | conf="$(dirname $0)/macoh.conf"
1013 | [[ -r "$conf" ]] && source "$conf"
1014 |
1015 | # Parse cmd line args (hack job, I know, will use getopts() later)
1016 | while [[ -n $@ ]]; do
1017 | [[ $1 = -c || $1 = -cmd ]] && shift && usercmd="$@" && break # -cmd must be the last option
1018 | [[ $1 = -w || $1 = -wait ]] && waitstart=$2 && waitend=$2 && shift 2 && continue
1019 | [[ $1 = -t || $1 = -time ]] && timeout=${2:-0} && shift 2 && continue
1020 | [[ $1 = -do ]] && do=$2 && shift 2 && continue
1021 | [[ $1 = -get ]] && get=$2 && shift 2 && continue
1022 | [[ $1 = -r || $1 = -res ]] && gpuwidth=${2/x*/} && gpuwidth=${2/*x/} && shift 2 && continue
1023 | [[ $1 = -m || $1 = -msaa ]] && gpumsaaa=$2 && shift 2 && continue
1024 | [[ $1 = -s || $1 = -gpuswitch ]] && gpuswitch=$2 && shift 2 && continue
1025 | [[ $1 = -g || $1 = -gputest ]] && gputest=$2 && shift 2 && continue
1026 | [[ $1 = -name ]] && testname=$2 && shift 2 && continue
1027 | [[ $1 = -plot ]] && {
1028 | testid=`basename ${2%.*}`
1029 | [[ $testid == *-*-* ]] || die $ERR_CMDLINE "-plot requires a filename YYYYMMDD-HHMMSS-NAME.log"
1030 | do=${testid#*-*-}
1031 | testid=${testid%-*}
1032 | justplot=1
1033 | shift 2
1034 | continue
1035 | }
1036 | die $ERR_CMDLINE "Unrecognized option '$1'"
1037 | done
1038 |
1039 | # init variables
1040 | moh-init $testid
1041 |
1042 | # Validate inputs / conf
1043 |
1044 | [[ $waitstart -gt 0 && $waitend -gt 0 ]] || die $ERR_CMDLINE "-w/-wait requires a positive integer"
1045 | [[ $gpuwidth -gt 0 && $gpuheight -gt 0 ]] || die $ERR_CMDLINE "-r/-res requires MxM, where M and N are positive integers"
1046 | [[ $gpumsaa = [0248] ]] || die $ERR_CMDLINE "-m/-msaa requires 0, 2, 4 or 8"
1047 | [[ $timeout -ge 0 ]] || die $ERR_CMDLINE "-t/-time requires a non-negative integer"
1048 | [[ ", $gputesttypes, " = *", $gputest, "* ]] || die $ERR_CMDLINE "-g/-gputest requires one of: $gputesttypes"
1049 |
1050 | # Cmd line GPU switch?
1051 | [[ -n $gpuswitch ]] && case $gpuswitch in
1052 | integrated) moh-gpuswitch 1; ecode=$?;;
1053 | discrete) moh-gpuswitch 2; ecode=$?;;
1054 | dynamic) moh-gpuswitch 3; ecode=$?;;
1055 | [012]) moh-gpuswitch $gpuswitch; ecode=$?;;
1056 | *) die $ERR_CMDLINE "-s/-gpuswitch requires one of: integrated, discrete, dynamic or 0, 1, 2"
1057 | esac
1058 |
1059 | [[ -n $justplot ]] && {
1060 | moh-plot $testid
1061 | exit $?
1062 | }
1063 |
1064 | # Cmd line predefined test?
1065 | [[ -n $do ]] && {
1066 | dolist=$(functionlist "moh-do-" ", ")
1067 | dore=$(functionlist "moh-do-" "|")
1068 | [[ $do =~ ^$dore$ ]] || die $ERR_CMDLINE "-do requires one of: $dolist"
1069 | [[ $do = gputest && -n $timeout ]] && gpuduration=$timeout
1070 | [[ $do = prime95 && -n $timeout ]] && p95duration=$timeout
1071 | moh-do-$do
1072 | exit $?
1073 | }
1074 |
1075 | # Cmd line fetch?
1076 | [[ -n $get ]] && {
1077 | getlist=$(functionlist "moh-get-" ", ")
1078 | getre=$(functionlist "moh-get-" "|")
1079 | [[ $get =~ ^$re$ ]] || die $ERR_CMDLINE "-get requires one of: $getlist"
1080 | moh-get-$get
1081 | exit $?
1082 | }
1083 |
1084 | # Cmd line user command?
1085 | [[ -n $usercmd ]] && {
1086 | [[ $timeout -ge 0 ]] && usercmdduration=$timeout
1087 | moh-cmd
1088 | exit $?
1089 | }
1090 |
1091 | # If only the -g/-gpuswitch was used, exit (allows scripting)
1092 | [[ -n $gpuswitch ]] && exit $ecode
1093 |
1094 | # If not, show menu
1095 | while [[ 1 ]]
1096 | do
1097 | # call this here to re-init testid and filename (date/time) or else
1098 | # tests will override each other if the user does not exit the menu
1099 | moh-init
1100 |
1101 | s_hbnice=`printf '%-5s' "[$hbnice]"`
1102 | s_gpunice=`printf '%-5s' "[$gpunice]"`
1103 | s_p95dur=`printf '%-10s' "[$(humantime $p95duration)]"`
1104 | s_gpudur=`printf '%-10s' "[$(humantime $gpuduration)]"`
1105 | s_res=`printf '%-11s' "[${gpuwidth}x$gpuheight]"`
1106 | s_p95min=`printf '%-8s' "[${p95min}k]"`
1107 | s_p95max=`printf '%-8s' "[${p95max}k]"`
1108 | s_fftsize=`printf '%-8s' "[$fftsize]"`
1109 | s_fftthreads=`printf '%-8s' "[$(getthreads $fftthreads)]"`
1110 | s_fftdur=`printf '%-10s' "[$(humantime $fftduration)]"`
1111 | [[ $p95mem = 0 ]] && s_p95mem='[in-place]' || s_p95mem=`printf '%-10s' "[${p95mem}MB]"`
1112 | s_p95time=`printf '%-8s' "[${p95time}m]"`
1113 |
1114 | echo -n "
1115 | -----------------------------------------------------------------------------
1116 | MacOH v1.5.4. Quit all other apps before launching.
1117 | ----------------------------------------------------------------------- TESTS
1118 | F. FFT multi-threaded (+ CPU stress)
1119 | X. Short x264 encode (++ CPU stress, 5-6 mins on Core i7-4850HQ)
1120 | Y. Long x264 encode (++ CPU stress, about 4 times longer)
1121 | P. Prime95 (++++ CPU stress, expect laptops to throttle)
1122 | G. 3D GpuTest (also try switching GPU beforehand)
1123 | S. Switch GPU to integrated or discrete
1124 | --------------------------------------------------------------------- OPTIONS
1125 | FD. FFT duration $s_fftdur PD. Prime95 duration $s_p95dur
1126 | FT. FFT threads $s_fftthreads PM. Prime95 memory $s_p95mem
1127 | FS. FFT size $s_fftsize PS. Prime95 fft min,max [${p95min}k,${p95max}k]
1128 | GD. GpuTest duration $s_gpudur GM. GpuTest MSAA [$gpumsaa]
1129 | GR. GpuTest res $s_res GT. GpuTest type [$gputest]
1130 | -------------------------------------------------------------------- DOWNLOAD
1131 | 1. Intel Power Gadget (2.3 MB) 5. Prime95 (1 MB)
1132 | 2. Graphics Layout Engine (13 MB) 6. HandBrakeCLI (6.9 MB)
1133 | 3. gfxCardStatus GPU switch (1 MB) 7. GpuTest (1.8 MB)
1134 | 4. Big Buck Bunny movie (691 MB)
1135 | -----------------------------------------------------------------------------
1136 | Your choice: [Q=Quit] "
1137 | read ans
1138 | echo
1139 | [[ -z $ans || $ans = q || $ans = Q ]] && exit 0
1140 |
1141 | set -e
1142 |
1143 | strcmpi $ans 1 && { moh-get-ipg; continue; }
1144 | strcmpi $ans 2 && { moh-get-gle; continue; }
1145 | strcmpi $ans 5 && { moh-get-prime95; continue; }
1146 | strcmpi $ans 7 && { moh-get-gputest; continue; }
1147 | strcmpi $ans 6 && { moh-get-handbrake; continue; }
1148 | strcmpi $ans 4 && { moh-get-video; continue; }
1149 | strcmpi $ans 3 && { moh-get-gfx; continue; }
1150 |
1151 | strcmpi $ans g && { moh-do-gputest; [[ $menuquit = 1 ]] && exit || { anykey; continue; } }
1152 | strcmpi $ans p && { moh-do-prime95; [[ $menuquit = 1 ]] && exit || { anykey; continue; } }
1153 | strcmpi $ans y && { moh-do-x264-long; [[ $menuquit = 1 ]] && exit || { anykey; continue; } }
1154 | strcmpi $ans x && { moh-do-x264; [[ $menuquit = 1 ]] && exit || { anykey; continue; } }
1155 | strcmpi $ans f && { moh-do-fft; [[ $menuquit = 1 ]] && exit || { anykey; continue; } }
1156 | strcmpi $ans s && { moh-gpuswitch-menu; continue; }
1157 |
1158 | strcmpi $ans fd && {
1159 | read -p "FFT duration in seconds: [$fftduration] " x;
1160 | [[ $x -gt 0 ]] && editconf fftduration $x && continue
1161 | [[ -z $x ]] && continue
1162 | menuerr="FFT test duration must be a number greater than 0"
1163 | }
1164 |
1165 | strcmpi $ans ft && {
1166 | read -p "FFT number of threads (-1=cores-1, 0=maxthreads, n=any n > 0): [$fftthreads] " x;
1167 | [[ $x -ge -1 ]] && editconf fftthreads $x && continue
1168 | [[ -z $x ]] && continue
1169 | menuerr="FFT number of threads must be greater or equal to -1"
1170 | }
1171 |
1172 | strcmpi $ans fs && {
1173 | read -p "FFT size: [$fftsize] " x;
1174 | [[ $x -gt 1 ]] && editconf fftsize $x && continue
1175 | [[ -z $x ]] && continue
1176 | menuerr="FFT size must be a number greater than 1"
1177 | }
1178 |
1179 | strcmpi $ans pd && {
1180 | read -p "Prime95 duration in seconds: [$p95duration] " x;
1181 | [[ $x -gt 0 ]] && editconf p95duration $x && continue
1182 | [[ -z $x ]] && continue
1183 | menuerr="The Prime95 test duration must be a number greater than 0"
1184 | }
1185 |
1186 | strcmpi $ans ps && {
1187 | read -p "Prime95 fft min,max sizes in thousands, e.g. 8,16: [$p95min,$p95max] " x
1188 | [[ -z $x ]] && continue
1189 | x=(${x/[^0-9]/ })
1190 | [[ ${x[0]} -le ${x[1]} && ${x[0]}${x[1]} =~ ^[0-9]+$ ]] && \
1191 | editconf p95min ${x[0]} && editconf p95max ${x[1]} && continue
1192 | menuerr="The Prime95 fft min,max sizes must be a pair of positive integers with min <= max, e.g. 8,16"
1193 | }
1194 |
1195 | strcmpi $ans pm && {
1196 | read -p "Prime95 FFT memory (MB), use 0 to do the FFTs in-place (CPU stressful): [$p95mem] " x
1197 | [[ -z $x ]] && continue
1198 | free=$(freemb)
1199 | [[ -n $free ]] && let free2=free/2
1200 | [[ $x -ge 0 && $x =~ ^[0-9]+$ && ( -z $free || $x -le $free2 ) ]] && editconf p95mem $x && continue
1201 | menuerr="The Prime95 FFT memory must be a positive integer less than half your free RAM ($free/2=$free2)"
1202 | }
1203 |
1204 | strcmpi $ans gd && {
1205 | read -p "GpuTest duration in seconds: [$gpuduration] " x;
1206 | [[ $x -gt 0 ]] && editconf gpuduration $x && continue
1207 | [[ -z $x ]] && continue
1208 | menuerr="Duration must be a number greater than 0"
1209 | }
1210 |
1211 | strcmpi $ans gt && {
1212 | menu "Choose GpuTest benchmark:" "$gputest" ${gputesttypes//,/}
1213 | [[ $menuchoice = $gputest ]] || editconf gputest $menuchoice
1214 | continue
1215 | }
1216 |
1217 | strcmpi $ans gp && {
1218 | read -p "GpuTest priority in -19...20 (smaller values means higher priority): [$gpunice] " x;
1219 | [[ -z $x ]] && continue
1220 | [[ $x =~ ^-?[0-9]+$ && $x -ge -19 && $x -le 20 ]] && editconf gpunice $x && {
1221 | [[ $x -lt 0 ]] && anykey "Negative value entered, your password will be required. Press any key to continue ..."
1222 | continue
1223 | }
1224 | menuerr="Priority (niceness) must be an integer in -19...20"
1225 | }
1226 |
1227 | strcmpi $ans gr && {
1228 | read -p "GpuTest resolution: [${gpuwidth}x$gpuheight] " x
1229 | [[ -z $x ]] && continue
1230 | [[ $x =~ ^[0-9]+x[0-9]+$ ]] && editconf gpuwidth ${x/x*/} \
1231 | && editconf gpuheight ${x/*x/} && continue
1232 | menuerr="Resolution must be MxN, where M and N are positive integers"
1233 | }
1234 |
1235 | strcmpi $ans gm && {
1236 | read -p "GpuTest MSAA value (0, 2, 4 or 8): [$gpumsaa] " x
1237 | [[ -z $x ]] && continue
1238 | [[ $x =~ ^[0248]$ ]] && editconf gpumsaa $x && continue
1239 | menuerr="MSAA value must be 0, 2, 4 or 8"
1240 | }
1241 |
1242 | strcmpi $ans hp && {
1243 | read -p "HandBrake priority in -19...20 (smaller values means higher priority): [$hbnice] " x;
1244 | [[ -z $x ]] && continue
1245 | [[ $x =~ ^-?[0-9]+$ && $x -ge -19 && $x -le 20 ]] && editconf hbnice $x && {
1246 | [[ $x -lt 0 ]] && anykey "Negative value entered, your password will be required. Press any key to continue ..."
1247 | continue
1248 | }
1249 | menuerr="Priority (niceness) must be an integer in -19...20"
1250 | }
1251 |
1252 | [[ -z $menuerr ]] && menuerr="Unknown option '$ans'"
1253 | anykey "Error: $menuerr. Press any key to continue ..."
1254 | done
1255 |
--------------------------------------------------------------------------------
/make-release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rm -f macoh.zip
4 | zip macoh.zip CHANGELOG.md LICENSE README.md fftwtest macoh.conf macoh.sh
5 |
--------------------------------------------------------------------------------
/mprime.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/qnxor/macoh/5f9195a515f04198b40b2021ca25f2caca26c054/mprime.tgz
--------------------------------------------------------------------------------