Skip to content

Commit

Permalink
Add Mandelbrot SIMD test to the benchmark tests
Browse files Browse the repository at this point in the history
  • Loading branch information
GorogPeter committed Sep 7, 2023
1 parent de7eb5f commit 46c03a5
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 2 deletions.
7 changes: 5 additions & 2 deletions test/wasmBenchmarker/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"prime": 48611,
"quick_sort": 0,
"red-black": 4000000,
"salesman": 840
"salesman": 840,
"simdMandelbrotCount": 775007
}
# https://benchmarksgame-team.pages.debian.net/benchmarksgame/description/simple.html#simple
gameTests = ["mandelbrot", "nbody", "gregory", "fannkuch", "k_nucleotide"]
Expand Down Expand Up @@ -111,8 +112,10 @@ def compile_tests(path, only_game=False, compile_anyway=False, run=None):
print("target files are found; compilation skipped")
continue

extraFlags = "-mavx -msimd128" if file.startswith("simd") else ""

print("compiling " + name)
bob_the_stringbuilder = "./emsdk/upstream/emscripten/emcc " + path + "/" + file + " --no-entry -s WASM=1 -s EXPORTED_FUNCTIONS=_runtime -s EXPORTED_RUNTIME_METHODS=ccall,cwrap -o " + path + "/wasm/" + name + ".wasm"
bob_the_stringbuilder = "./emsdk/upstream/emscripten/emcc " + path + "/" + file + " " + extraFlags + " --no-entry -s WASM=1 -s EXPORTED_FUNCTIONS=_runtime -s EXPORTED_RUNTIME_METHODS=ccall,cwrap -o " + path + "/wasm/" + name + ".wasm"
os.system(bob_the_stringbuilder)

return test_names
Expand Down
92 changes: 92 additions & 0 deletions test/wasmBenchmarker/ctests/simdMandelbrotCount.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright (c) 2023-present Samsung Electronics Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

#include <immintrin.h> // SIMD header

#define WIDTH 1600
#define HIGHT 1400
#define N 20
#define REAL_AXIS_SHIFT -1.8 // ~ horizontal shift
#define IMAGINARY_AXIS_SHIFT -1.0 // ~ vertical shift
#define ZOOM 0.0015

#define getNthBit(b, n) ((b & (0b00000001 << (7 - n))) > 0)

#define setNthBitZero(b, n) b = b & (0b11111111 - (0b00000001 << (7 - n)))

#define setNthBitOne(b, n) b = b | (0b00000001 << (7 - n))

#define SQUARE(num) _mm_mul_ps(num, num)

#define ABS_COMPLEX(z_real, z_complex) _mm_sqrt_ps(_mm_add_ps(SQUARE(z_real), SQUARE(z_imaginary)))

typedef uint8_t byte;

byte areInMandelbrotSet(__m128 c_real, __m128 c_imaginary);

uint32_t runtime();

int main() {
if (WIDTH % 4 != 0) {
return 1;
}
printf("%u\n", runtime());
return 0;
}

byte areInMandelbrotSet(__m128 c_real, __m128 c_imaginary)
{
byte result = 0b11110000;
__m128 z_real = _mm_set1_ps(0);
__m128 z_imaginary = _mm_set1_ps(0);
for (size_t i = 0; i < N; i++) {
__m128 cmp_result = _mm_cmpgt_ps(ABS_COMPLEX(z_real, z_imaginary), _mm_set1_ps(2));
for (size_t j = 0; j < 4; j++) {
if (getNthBit(result, j) == 1 && ((float*)&cmp_result)[j] != 0) {
setNthBitZero(result, j);
}
}
__m128 next_z_real = _mm_add_ps(_mm_sub_ps(SQUARE(z_real), SQUARE(z_imaginary)), c_real);
__m128 next_z_imaginary = _mm_add_ps(_mm_mul_ps(_mm_mul_ps(z_real, z_imaginary), _mm_set1_ps(2)), c_imaginary);
z_real = next_z_real;
z_imaginary = next_z_imaginary;
if (result == 0b00000000) {
break;
}
}
return result;
}

uint32_t runtime() {
uint32_t setSize = 0;
for (int i = 0; i < HIGHT; i++) {
for (int j = 0; j < WIDTH; j+=4) {
__m128 real = _mm_add_ps(_mm_mul_ps(_mm_set_ps(j+3, j+2, j+1, j), _mm_set1_ps(ZOOM)), _mm_set1_ps(REAL_AXIS_SHIFT));
__m128 imaginary = _mm_add_ps(_mm_mul_ps(_mm_set1_ps(i), _mm_set1_ps(ZOOM)), _mm_set1_ps(IMAGINARY_AXIS_SHIFT));
byte pixels = areInMandelbrotSet(real, imaginary);
for (int i = 0; i < 4; i++) {
if (getNthBit(pixels, i)) {
setSize++;
}
}
}
}
return setSize;
}

0 comments on commit 46c03a5

Please sign in to comment.