具有AVX寄存器的Union类成员可以减少内存访问?

时间:2015-09-08 16:23:59

标签: c++ performance optimization avx

如果我有一个包含指针,浮点数,双精度数,int32和int16混合的类(或结构),我可以将该类与AVX寄存器合并,然后通过联合访问数据以强制编译器加载数据全部在一起?

我正在尝试减少内存负载。

1 个答案:

答案 0 :(得分:3)

你可以做到,它会起作用(如果结构足够小),但它最终会变得更快。 除了您想要将整个结构复制为32字节块的情况之外。

如果您单独加载所有成员,那么您将在程序集中看到许多加载指令,如private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { ImageView bmImage; public DownloadImageTask(ImageView bmImage) { this.bmImage = bmImage; } protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; HttpURLConnection urlConnection = null; Bitmap mIcon11 = null; try { if (urldisplay == null) { return null; } else { URL uri = new URL(urldisplay); urlConnection = (HttpURLConnection) uri.openConnection(); int statusCode = urlConnection.getResponseCode(); if (statusCode != HttpStatus.SC_OK) { return null; } if (urlConnection != null) { InputStream in = urlConnection.getInputStream(); if (in != null) { mIcon11 = BitmapFactory.decodeStream(in); return mIcon11; } else { return null; } } else { return null; } } } catch (Exception e) { if (urlConnection != null) { urlConnection.disconnect(); } Log.e("", e.getLocalizedMessage()); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } return mIcon11; } protected void onPostExecute(Bitmap result) { if (result != null) { bmImage.setImageBitmap(result); } else { Drawable placeholder = bmImage.getContext().getResources().getDrawable(R.drawable.default_img); bmImage.setImageDrawable(placeholder); } bmImage.setScaleType(ScaleType.FIT_XY); } } 。您似乎希望减少这些指令的数量。

您确实可以将它们加载为mov eax, [esi + 10h]类型的一个AVX值,然后您只会看到__m256之类的一条指令。但是,该负载的结果将在256位YMM寄存器中。您无法免费访问此注册表的部分内容。

XMM和YMM寄存器主要充当大块数据,您可以轻松地对8位增加32位整数,但是您无法快速访问这些256位块的任意部分。您仍然可以尝试提取YMM寄存器的部分内容,但它需要额外的指令(至少与标量版本中vmovaps ymm0, [esi] - s的数量一样多),因此生成的代码会更慢。

如果你真的想要提取AVX寄存器的部分内容,请确保在结构上使用mov并手动对齐其数据成员,因为否则成员的偏移量可能因编译器和位数而异。

您可能关心的另一件事是实际内存事务的数量。您可能认为一个256位负载比许多单独的32位和16位负载快。在我看来,这不是真的:内存是在缓存行粒度上运行的。每个64字节的内存块是单个缓存行,处理器只能加载整个缓存行。在这两种情况下,都会加载相同数量的缓存行,因此内存访问不会更快。