Benchmarking sigmoid function between C and D

Daniel Kozak kozzi11 at gmail.com
Sat Apr 7 19:10:50 UTC 2018


can you try it with c math functions?

instead of std.math, try to use core.stdc.math

On Sat, Apr 7, 2018 at 8:53 PM, Arun Chandrasekaran via Digitalmars-d-learn
<digitalmars-d-learn at puremagic.com> wrote:

> What am I doing wrong here that makes the D equivalent 2.5 times slower
> than it's C equivalent?
>
> Compilers used:
>
> LDC2: LDC - the LLVM D compiler (1.8.0)
> GCC: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
>
> 11:36:39 ~/code/c/test2$ ldc2 sigmoid.d -O5 && ./sigmoid
> Max deviation is 0.001664
> 10^7 iterations using sigmoid1: 308 ms
> 10^7 iterations using sigmoid2: 30 ms
> 11:36:55 ~/code/c/test2
> $ gcc sigmoid.c -o sigmoid-c -O3 -lm 2>/dev/null && ./sigmoid-c
> Max deviation is 0.001664
> 10^7 iterations using sigmoid1: 134 ms
> 10^7 iterations using sigmoid2: 29 ms
> 11:37:10 ~/code/c/test2
> $
>
> C code, taken from https://stackoverflow.com/ques
> tions/412019/math-optimization-in-c-sharp#412176:
>
> ```
> #include <math.h>
> #include <stdio.h>
> #include <time.h>
>
> #define SCALE 320.0f
> #define RESOLUTION 2047
> #define MIN -RESOLUTION / SCALE
> #define MAX RESOLUTION / SCALE
>
> static float sigmoid_lut[RESOLUTION + 1];
>
> void init_sigmoid_lut(void) {
>     int i;
>     for (i = 0; i < RESOLUTION + 1; i++) {
>         sigmoid_lut[i] =  (1.0 / (1.0 + exp(-i / SCALE)));
>     }
> }
>
> static float sigmoid1(const float value) {
>     return (1.0f / (1.0f + expf(-value)));
> }
>
> static float sigmoid2(const float value) {
>     if (value <= MIN) return 0.0f;
>     if (value >= MAX) return 1.0f;
>     if (value >= 0) return sigmoid_lut[(int)(value * SCALE + 0.5f)];
>     return 1.0f-sigmoid_lut[(int)(-value * SCALE + 0.5f)];
> }
>
> float test_error() {
>     float x;
>     float emax = 0.0;
>
>     for (x = -10.0f; x < 10.0f; x+=0.00001f) {
>         float v0 = sigmoid1(x);
>         float v1 = sigmoid2(x);
>         float error = fabsf(v1 - v0);
>         if (error > emax) { emax = error; }
>     }
>     return emax;
> }
>
> int sigmoid1_perf() {
>     clock_t t0, t1;
>     int i;
>     float x, y = 0.0f;
>
>     t0 = clock();
>     for (i = 0; i < 10; i++) {
>         for (x = -5.0f; x <= 5.0f; x+=0.00001f) {
>             y = sigmoid1(x);
>         }
>     }
>     t1 = clock();
>     printf("", y); /* To avoid sigmoidX() calls being optimized away */
>     return (t1 - t0) / (CLOCKS_PER_SEC / 1000);
> }
>
> int sigmoid2_perf() {
>     clock_t t0, t1;
>     int i;
>     float x, y = 0.0f;
>     t0 = clock();
>     for (i = 0; i < 10; i++) {
>         for (x = -5.0f; x <= 5.0f; x+=0.00001f) {
>             y = sigmoid2(x);
>         }
>     }
>     t1 = clock();
>     printf("", y); /* To avoid sigmoidX() calls being optimized away */
>     return (t1 - t0) / (CLOCKS_PER_SEC / 1000);
> }
>
> int main(void) {
>     init_sigmoid_lut();
>     printf("Max deviation is %0.6f\n", test_error());
>     printf("10^7 iterations using sigmoid1: %d ms\n", sigmoid1_perf());
>     printf("10^7 iterations using sigmoid2: %d ms\n", sigmoid2_perf());
>
>     return 0;
> }
> ```
>
> D equivalent:
>
> ```
> module sigmoid;
>
> import std.stdio;
> import std.math;
> import std.datetime.stopwatch;
>
> enum SCALE = 320.0f;
> enum RESOLUTION = 2047;
> enum MIN = -RESOLUTION / SCALE;
> enum MAX = RESOLUTION / SCALE;
>
> float[RESOLUTION + 1] sigmoid_lut;
>
> void init_sigmoid_lut() {
>     int i;
>     for (i = 0; i < RESOLUTION + 1; i++) {
>         sigmoid_lut[i] =  (1.0 / (1.0 + exp(-i / SCALE)));
>     }
> }
>
> private float sigmoid1(const float value) {
>     return (1.0f / (1.0f + exp(-value)));
> }
>
> private float sigmoid2(const float value) {
>     if (value <= MIN) return 0.0f;
>     if (value >= MAX) return 1.0f;
>     if (value >= 0) return sigmoid_lut[cast(int)(value * SCALE + 0.5f)];
>     return 1.0f-sigmoid_lut[cast(int)(-value * SCALE + 0.5f)];
> }
>
> private float test_error() {
>     float x;
>     float emax = 0.0;
>
>     for (x = -10.0f; x < 10.0f; x+=0.00001f) {
>         float v0 = sigmoid1(x);
>         float v1 = sigmoid2(x);
>         float error = fabs(v1 - v0);
>         if (error > emax) { emax = error; }
>     }
>     return emax;
> }
>
> private auto sigmoid1_perf() {
>     auto sw = StopWatch(AutoStart.yes);
>     int i;
>     float x, y = 0.0f;
>
>     for (i = 0; i < 10; i++) {
>         for (x = -5.0f; x <= 5.0f; x+=0.00001f) {
>             y = sigmoid1(x);
>         }
>     }
>     return sw.peek.total!"msecs";
> }
>
> private auto sigmoid2_perf() {
>     auto sw = StopWatch(AutoStart.yes);
>     int i;
>     float x, y = 0.0f;
>     for (i = 0; i < 10; i++) {
>         for (x = -5.0f; x <= 5.0f; x+=0.00001f) {
>             y = sigmoid2(x);
>         }
>     }
>     return sw.peek.total!"msecs";
> }
>
> int main() {
>     init_sigmoid_lut();
>     writefln("Max deviation is %0.6f", test_error());
>     writefln("10^7 iterations using sigmoid1: %s ms", sigmoid1_perf());
>     writefln("10^7 iterations using sigmoid2: %s ms", sigmoid2_perf());
>
>     return 0;
> }
> ```
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20180407/5091022b/attachment-0001.html>


More information about the Digitalmars-d-learn mailing list